xthread 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/queue.c ADDED
@@ -0,0 +1,393 @@
1
+ /**********************************************************************
2
+
3
+ queue.c -
4
+
5
+ Copyright (C) 2011 Keiju Ishitsuka
6
+ Copyright (C) 2011 Penta Advanced Laboratories, Inc.
7
+
8
+ **********************************************************************/
9
+
10
+ #include "ruby.h"
11
+
12
+ #include "xthread.h"
13
+
14
+ #define SIZED_QUEUE_DEFAULT_MAX 16
15
+
16
+ VALUE rb_cXThreadQueue;
17
+ VALUE rb_cXThreadSizedQueue;
18
+
19
+ typedef struct rb_xthread_queue_struct
20
+ {
21
+ VALUE lock;
22
+ VALUE cond;
23
+
24
+ VALUE elements;
25
+ } xthread_queue_t;
26
+
27
+ #define GetXThreadQueuePtr(obj, tobj) \
28
+ TypedData_Get_Struct((obj), xthread_queue_t, &xthread_queue_data_type, (tobj))
29
+
30
+ static void
31
+ xthread_queue_mark(void *ptr)
32
+ {
33
+ xthread_queue_t *que = (xthread_queue_t*)ptr;
34
+
35
+ rb_gc_mark(que->lock);
36
+ rb_gc_mark(que->cond);
37
+ rb_gc_mark(que->elements);
38
+ }
39
+
40
+ static void
41
+ xthread_queue_free(void *ptr)
42
+ {
43
+ ruby_xfree(ptr);
44
+ }
45
+
46
+ static size_t
47
+ xthread_queue_memsize(const void *ptr)
48
+ {
49
+ return ptr ? sizeof(xthread_queue_t) : 0;
50
+ }
51
+
52
+ static const rb_data_type_t xthread_queue_data_type = {
53
+ "xthread_queue",
54
+ {xthread_queue_mark, xthread_queue_free, xthread_queue_memsize,},
55
+ };
56
+
57
+ static void
58
+ xthread_queue_alloc_init(xthread_queue_t *que)
59
+ {
60
+ que->lock = rb_mutex_new();
61
+ que->cond = rb_xthread_cond_new();
62
+ que->elements = rb_xthread_fifo_new();
63
+ }
64
+
65
+ static VALUE
66
+ xthread_queue_alloc(VALUE klass)
67
+ {
68
+ VALUE volatile obj;
69
+ xthread_queue_t *que;
70
+
71
+ obj = TypedData_Make_Struct(klass, xthread_queue_t, &xthread_queue_data_type, que);
72
+ xthread_queue_alloc_init(que);
73
+ return obj;
74
+ }
75
+
76
+ static VALUE
77
+ xthread_queue_initialize(VALUE self)
78
+ {
79
+ return self;
80
+ }
81
+
82
+ VALUE
83
+ rb_xthread_queue_new(void)
84
+ {
85
+ return xthread_queue_alloc(rb_cXThreadQueue);
86
+ }
87
+
88
+ VALUE
89
+ rb_xthread_queue_push(VALUE self, VALUE item)
90
+ {
91
+ xthread_queue_t *que;
92
+ int signal_p = 0;
93
+
94
+ GetXThreadQueuePtr(self, que);
95
+
96
+ if (RTEST(rb_xthread_fifo_empty_p(que->elements))) {
97
+ signal_p = 1;
98
+ }
99
+ rb_xthread_fifo_push(que->elements, item);
100
+ if (signal_p) {
101
+ rb_xthread_cond_signal(que->cond);
102
+ }
103
+ return self;
104
+ }
105
+
106
+ VALUE
107
+ rb_xthread_queue_pop(VALUE self)
108
+ {
109
+ xthread_queue_t *que;
110
+ VALUE item;
111
+
112
+ GetXThreadQueuePtr(self, que);
113
+
114
+ if (RTEST(rb_xthread_fifo_empty_p(que->elements))) {
115
+ rb_mutex_lock(que->lock);
116
+ while (RTEST(rb_xthread_fifo_empty_p(que->elements))) {
117
+ rb_xthread_cond_wait(que->cond, que->lock, Qnil);
118
+ }
119
+ rb_mutex_unlock(que->lock);
120
+ }
121
+ return rb_xthread_fifo_pop(que->elements);
122
+ }
123
+
124
+ VALUE
125
+ rb_xthread_queue_pop_non_block(VALUE self)
126
+ {
127
+ xthread_queue_t *que;
128
+ VALUE item;
129
+
130
+ GetXThreadQueuePtr(self, que);
131
+
132
+ if (RTEST(rb_xthread_fifo_empty_p(que->elements))) {
133
+ rb_raise(rb_eThreadError, "xthread_queue empty");
134
+ }
135
+ else {
136
+ return rb_xthread_fifo_pop(que->elements);
137
+ }
138
+ }
139
+
140
+ static VALUE
141
+ xthread_queue_pop(int argc, VALUE *argv, VALUE self)
142
+ {
143
+ VALUE non_block;
144
+
145
+ rb_scan_args(argc, argv, "01", &non_block);
146
+ if (RTEST(non_block)) {
147
+ return rb_xthread_queue_pop_non_block(self);
148
+ }
149
+ else {
150
+ return rb_xthread_queue_pop(self);
151
+ }
152
+ }
153
+
154
+
155
+ VALUE
156
+ rb_xthread_queue_empty_p(VALUE self)
157
+ {
158
+ xthread_queue_t *que;
159
+ GetXThreadQueuePtr(self, que);
160
+
161
+ return rb_xthread_fifo_empty_p(que->elements);
162
+ }
163
+
164
+ VALUE
165
+ rb_xthread_queue_clear(VALUE self)
166
+ {
167
+ xthread_queue_t *que;
168
+ GetXThreadQueuePtr(self, que);
169
+
170
+ rb_xthread_fifo_clear(que->elements);
171
+ return self;
172
+ }
173
+
174
+ VALUE
175
+ rb_xthread_queue_length(VALUE self)
176
+ {
177
+ xthread_queue_t *que;
178
+ GetXThreadQueuePtr(self, que);
179
+
180
+ return rb_xthread_fifo_length(que->elements);
181
+ }
182
+
183
+ typedef struct rb_xthread_sized_queue_struct
184
+ {
185
+ xthread_queue_t super;
186
+
187
+ long max;
188
+ VALUE cond_wait;
189
+
190
+ } xthread_sized_queue_t;
191
+
192
+ #define GetXThreadSizedQueuePtr(obj, tobj) \
193
+ TypedData_Get_Struct((obj), xthread_sized_queue_t, &xthread_sized_queue_data_type, (tobj))
194
+
195
+ static void
196
+ xthread_sized_queue_mark(void *ptr)
197
+ {
198
+ xthread_sized_queue_t *que = (xthread_sized_queue_t*)ptr;
199
+
200
+ xthread_queue_mark(ptr);
201
+ rb_gc_mark(que->cond_wait);
202
+ }
203
+
204
+ static void
205
+ xthread_sized_queue_free(void *ptr)
206
+ {
207
+ xthread_sized_queue_t *que = (xthread_sized_queue_t*)ptr;
208
+
209
+ ruby_xfree(ptr);
210
+ }
211
+
212
+ static size_t
213
+ xthread_sized_queue_memsize(const void *ptr)
214
+ {
215
+ xthread_sized_queue_t *que = (xthread_sized_queue_t*)ptr;
216
+
217
+ return ptr ? sizeof(xthread_sized_queue_t) : 0;
218
+ }
219
+
220
+ static const rb_data_type_t xthread_sized_queue_data_type = {
221
+ "xthread_sized_queue",
222
+ {xthread_sized_queue_mark, xthread_sized_queue_free, xthread_sized_queue_memsize,},
223
+ &xthread_queue_data_type,
224
+ };
225
+
226
+ static VALUE
227
+ xthread_sized_queue_alloc(VALUE klass)
228
+ {
229
+ VALUE volatile obj;
230
+ xthread_sized_queue_t *que;
231
+
232
+ obj = TypedData_Make_Struct(klass,
233
+ xthread_sized_queue_t, &xthread_sized_queue_data_type, que);
234
+ xthread_queue_alloc_init(&que->super);
235
+
236
+ que->max = SIZED_QUEUE_DEFAULT_MAX;
237
+ que->cond_wait = rb_xthread_cond_new();
238
+
239
+ return obj;
240
+ }
241
+
242
+ static VALUE
243
+ xthread_sized_queue_initialize(VALUE self, VALUE v_max)
244
+ {
245
+ xthread_sized_queue_t *que;
246
+ long max = NUM2LONG(v_max);
247
+
248
+ GetXThreadSizedQueuePtr(self, que);
249
+
250
+ que->max = max;
251
+
252
+ return self;
253
+ }
254
+
255
+ VALUE
256
+ rb_xthread_sized_queue_new(long max)
257
+ {
258
+ xthread_sized_queue_t *que;
259
+ VALUE obj = xthread_sized_queue_alloc(rb_cXThreadSizedQueue);
260
+
261
+ GetXThreadSizedQueuePtr(obj, que);
262
+
263
+ que->max = max;
264
+ return obj;
265
+ }
266
+
267
+ VALUE
268
+ rb_xthread_sized_queue_max(VALUE self)
269
+ {
270
+ xthread_sized_queue_t *que;
271
+
272
+ GetXThreadSizedQueuePtr(self, que);
273
+ return LONG2NUM(que->max);
274
+ }
275
+
276
+ VALUE
277
+ rb_xthread_sized_queue_set_max(VALUE self, VALUE v_max)
278
+ {
279
+ xthread_sized_queue_t *que;
280
+ long max = NUM2LONG(v_max);
281
+ long diff = 0;
282
+ long i;
283
+
284
+ GetXThreadSizedQueuePtr(self, que);
285
+
286
+ if (max < que->max) {
287
+ diff = max - que->max;
288
+ }
289
+ que->max = max;
290
+
291
+ for (i = 0; i < diff; i++) {
292
+ rb_xthread_cond_signal(que->cond_wait);
293
+ }
294
+ }
295
+
296
+ VALUE
297
+ rb_xthread_sized_queue_push(VALUE self, VALUE item)
298
+ {
299
+ xthread_sized_queue_t *que;
300
+
301
+ GetXThreadSizedQueuePtr(self, que);
302
+
303
+ if (NUM2LONG(rb_xthread_fifo_length(que->super.elements)) < que->max) {
304
+ return rb_xthread_queue_push(self, item);
305
+ }
306
+ rb_mutex_lock(que->super.lock);
307
+ while (NUM2LONG(rb_xthread_fifo_length(que->super.elements)) >= que->max) {
308
+ rb_xthread_cond_wait(que->cond_wait, que->super.lock, Qnil);
309
+ }
310
+ rb_mutex_unlock(que->super.lock);
311
+ return rb_xthread_queue_push(self, item);
312
+ }
313
+
314
+ VALUE
315
+ rb_xthread_sized_queue_pop(VALUE self)
316
+ {
317
+ VALUE item;
318
+ xthread_sized_queue_t *que;
319
+ GetXThreadSizedQueuePtr(self, que);
320
+
321
+ item = rb_xthread_queue_pop(self);
322
+
323
+ if (NUM2LONG(rb_xthread_fifo_length(que->super.elements)) < que->max) {
324
+ rb_xthread_cond_signal(que->cond_wait);
325
+ }
326
+ return item;
327
+ }
328
+
329
+ VALUE
330
+ rb_xthread_sized_queue_pop_non_block(VALUE self)
331
+ {
332
+ VALUE item;
333
+ xthread_sized_queue_t *que;
334
+ GetXThreadSizedQueuePtr(self, que);
335
+
336
+ item = rb_xthread_queue_pop_non_block(self);
337
+
338
+ if (NUM2LONG(rb_xthread_fifo_length(que->super.elements)) < que->max) {
339
+ rb_xthread_cond_signal(que->cond_wait);
340
+ }
341
+ return item;
342
+ }
343
+
344
+ static VALUE
345
+ xthread_sized_queue_pop(int argc, VALUE *argv, VALUE self)
346
+ {
347
+ VALUE item;
348
+ xthread_sized_queue_t *que;
349
+ GetXThreadSizedQueuePtr(self, que);
350
+
351
+ item = xthread_queue_pop(argc, argv, self);
352
+
353
+ if (NUM2LONG(rb_xthread_fifo_length(que->super.elements)) < que->max) {
354
+ rb_xthread_cond_signal(que->cond_wait);
355
+ }
356
+ return item;
357
+ }
358
+
359
+ void
360
+ Init_XThreadQueue()
361
+ {
362
+ rb_cXThreadQueue = rb_define_class_under(rb_mXThread, "Queue", rb_cObject);
363
+
364
+ rb_define_alloc_func(rb_cXThreadQueue, xthread_queue_alloc);
365
+ rb_define_method(rb_cXThreadQueue, "initialize", xthread_queue_initialize, 0);
366
+ rb_define_method(rb_cXThreadQueue, "pop", xthread_queue_pop, -1);
367
+ rb_define_alias(rb_cXThreadQueue, "shift", "pop");
368
+ rb_define_alias(rb_cXThreadQueue, "deq", "pop");
369
+ rb_define_method(rb_cXThreadQueue, "push", rb_xthread_queue_push, 1);
370
+ rb_define_alias(rb_cXThreadQueue, "<<", "push");
371
+ rb_define_alias(rb_cXThreadQueue, "enq", "push");
372
+ rb_define_method(rb_cXThreadQueue, "empty?", rb_xthread_queue_empty_p, 0);
373
+ rb_define_method(rb_cXThreadQueue, "clear", rb_xthread_queue_clear, 0);
374
+ rb_define_method(rb_cXThreadQueue, "length", rb_xthread_queue_length, 0);
375
+ rb_define_alias(rb_cXThreadQueue, "size", "length");
376
+
377
+
378
+ rb_cXThreadSizedQueue = rb_define_class_under(rb_mXThread, "SizedQueue", rb_cXThreadQueue);
379
+
380
+ rb_define_alloc_func(rb_cXThreadSizedQueue, xthread_sized_queue_alloc);
381
+ rb_define_method(rb_cXThreadSizedQueue, "initialize", xthread_sized_queue_initialize, 1);
382
+ rb_define_method(rb_cXThreadSizedQueue, "pop", xthread_sized_queue_pop, 0);
383
+ rb_define_alias(rb_cXThreadSizedQueue, "shift", "pop");
384
+ rb_define_alias(rb_cXThreadSizedQueue, "deq", "pop");
385
+ rb_define_method(rb_cXThreadSizedQueue, "push", rb_xthread_sized_queue_push, 1);
386
+ rb_define_alias(rb_cXThreadSizedQueue, "<<", "push");
387
+ rb_define_alias(rb_cXThreadSizedQueue, "enq", "push");
388
+
389
+ rb_define_method(rb_cXThreadSizedQueue, "max", rb_xthread_sized_queue_max, 0);
390
+ rb_define_method(rb_cXThreadSizedQueue, "max=", rb_xthread_sized_queue_set_max, 1);
391
+
392
+
393
+ }
data/xthread.c ADDED
@@ -0,0 +1,28 @@
1
+ /**********************************************************************
2
+
3
+ xthread.c -
4
+
5
+ Copyright (C) 2011 Keiju Ishitsuka
6
+ Copyright (C) 2011 Penta Advanced Laboratories, Inc.
7
+
8
+ **********************************************************************/
9
+
10
+ #include "ruby.h"
11
+
12
+ extern void Init_XThreadFifo();
13
+ extern void Init_XThreadCond();
14
+ extern void Init_XThreadQueue();
15
+ extern void Init_XThreadMonitor();
16
+
17
+ VALUE rb_mXThread;
18
+
19
+ Init_xthread()
20
+ {
21
+ rb_mXThread = rb_define_module("XThread");
22
+
23
+ Init_XThreadFifo();
24
+ Init_XThreadCond();
25
+ Init_XThreadQueue();
26
+ Init_XThreadMonitor();
27
+ }
28
+
data/xthread.gemspec ADDED
@@ -0,0 +1,32 @@
1
+
2
+ require "rubygems"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "xthread"
6
+ s.authors = "Keiju.Ishitsuka"
7
+ s.email = "keiju@ishitsuka.com"
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = "C-implementation version of thread.rb and monitor.eb libraries"
10
+ s.rubyforge_project = s.name
11
+ s.homepage = "http://github.com/keiju/xthread"
12
+ s.version = `git tag`.split.collect{|e| e.sub(/v([0-9]+\.[0-9]+\.[0-9]+).*/, "\\1")}.sort.last
13
+ s.require_path = "."
14
+ # s.test_file = ""
15
+ # s.executable = ""
16
+ s.files = ["LICENSE", "xthread.gemspec"]
17
+ s.files.concat Dir.glob("*.h")
18
+ s.files.concat Dir.glob("*.c")
19
+ s.files.concat Dir.glob("lib/*.rb")
20
+ s.files.concat Dir.glob("lib/xthread/*.rb")
21
+
22
+ s.extensions = ["extconf.rb"]
23
+ s.description = <<EOF
24
+ C-implementation version of thread.rb and monitor.eb libraries
25
+ EOF
26
+ end
27
+
28
+ # Editor settings
29
+ # - Emacs -
30
+ # local variables:
31
+ # mode: Ruby
32
+ # end:
data/xthread.h ADDED
@@ -0,0 +1,65 @@
1
+ /**********************************************************************
2
+
3
+ xthread.h -
4
+
5
+ Copyright (C) 2011 Keiju Ishitsuka
6
+ Copyright (C) 2011 Penta Advanced Laboratories, Inc.
7
+
8
+ **********************************************************************/
9
+
10
+
11
+ #define XTHREAD_VERSION "0.1.2"
12
+
13
+ RUBY_EXTERN VALUE rb_mXThread;
14
+ RUBY_EXTERN VALUE rb_cXThreadFifo;
15
+ RUBY_EXTERN VALUE rb_cXThreadConditionVariable;
16
+ RUBY_EXTERN VALUE rb_cXThreadQueue;
17
+ RUBY_EXTERN VALUE rb_cXThreadSizedQueue;
18
+ RUBY_EXTERN VALUE rb_cXThreadMonitor;
19
+ RUBY_EXTERN VALUE rb_cXThreadMonitorCond;
20
+
21
+
22
+ RUBY_EXTERN VALUE rb_xthread_fifo_new(void);
23
+ RUBY_EXTERN VALUE rb_xthread_fifo_empty_p(VALUE);
24
+ RUBY_EXTERN VALUE rb_xthread_fifo_push(VALUE, VALUE);
25
+ RUBY_EXTERN VALUE rb_xthread_fifo_pop(VALUE);
26
+ RUBY_EXTERN VALUE rb_xthread_fifo_clear(VALUE);
27
+ RUBY_EXTERN VALUE rb_xthread_fifo_length(VALUE);
28
+
29
+ RUBY_EXTERN VALUE rb_xthread_cond_new(void);
30
+ RUBY_EXTERN VALUE rb_xthread_cond_signal(VALUE);
31
+ RUBY_EXTERN VALUE rb_xthread_cond_broadcast(VALUE);
32
+ RUBY_EXTERN VALUE rb_xthread_cond_wait(VALUE, VALUE, VALUE);
33
+
34
+ RUBY_EXTERN VALUE rb_xthread_queue_new(void);
35
+ RUBY_EXTERN VALUE rb_xthread_queue_push(VALUE, VALUE);
36
+ RUBY_EXTERN VALUE rb_xthread_queue_pop(VALUE);
37
+ RUBY_EXTERN VALUE rb_xthread_queue_pop_non_block(VALUE);
38
+ RUBY_EXTERN VALUE rb_xthread_queue_empty_p(VALUE);
39
+ RUBY_EXTERN VALUE rb_xthread_queue_clear(VALUE);
40
+ RUBY_EXTERN VALUE rb_xthread_queue_length(VALUE);
41
+
42
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_new(long);
43
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_max(VALUE);
44
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_set_max(VALUE, VALUE);
45
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_push(VALUE, VALUE);
46
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_pop(VALUE);
47
+ RUBY_EXTERN VALUE rb_xthread_sized_queue_pop_non_block(VALUE);
48
+
49
+ RUBY_EXTERN VALUE rb_xthread_monitor_new(void);
50
+ RUBY_EXTERN VALUE rb_xthread_monitor_try_enter(VALUE);
51
+ RUBY_EXTERN VALUE rb_xthread_monitor_enter(VALUE);
52
+ RUBY_EXTERN VALUE rb_xthread_monitor_exit(VALUE);
53
+ RUBY_EXTERN VALUE rb_xthread_monitor_synchronize(VALUE, VALUE (*)(VALUE), VALUE);
54
+ RUBY_EXTERN VALUE rb_xthread_monitor_new_cond(VALUE);
55
+
56
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_new(VALUE);
57
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_wait(VALUE, VALUE);
58
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_wait_while(VALUE);
59
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_wait_until(VALUE);
60
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_signal(VALUE);
61
+ RUBY_EXTERN VALUE rb_xthread_monitor_cond_broadcast(VALUE self);
62
+
63
+
64
+
65
+
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xthread
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 3
10
+ version: 0.1.3
11
+ platform: ruby
12
+ authors:
13
+ - Keiju.Ishitsuka
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-10 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: |
23
+ C-implementation version of thread.rb and monitor.eb libraries
24
+
25
+ email: keiju@ishitsuka.com
26
+ executables: []
27
+
28
+ extensions:
29
+ - extconf.rb
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - LICENSE
34
+ - xthread.gemspec
35
+ - xthread.h
36
+ - monitor.c
37
+ - xthread.c
38
+ - cond.c
39
+ - fifo.c
40
+ - queue.c
41
+ - lib/xthread.rb
42
+ - lib/xthread/monitor.rb
43
+ - extconf.rb
44
+ has_rdoc: true
45
+ homepage: http://github.com/keiju/xthread
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - .
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ requirements: []
72
+
73
+ rubyforge_project: xthread
74
+ rubygems_version: 1.3.7
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: C-implementation version of thread.rb and monitor.eb libraries
78
+ test_files: []
79
+