xthread 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/cond.c +152 -0
- data/extconf.rb +4 -0
- data/fifo.c +269 -0
- data/lib/xthread/monitor.rb +282 -0
- data/lib/xthread.rb +252 -0
- data/monitor.c +404 -0
- data/queue.c +393 -0
- data/xthread.c +28 -0
- data/xthread.gemspec +32 -0
- data/xthread.h +65 -0
- metadata +79 -0
data/lib/xthread.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
#
|
2
|
+
# xthread.rb -
|
3
|
+
# Copyright (C) 2011 Keiju Ishitsuka
|
4
|
+
# Copyright (C) 2011 Penta Advanced Laboratories, Inc.
|
5
|
+
#
|
6
|
+
#
|
7
|
+
|
8
|
+
require "xthread.so"
|
9
|
+
|
10
|
+
unless defined? Thread
|
11
|
+
raise "Thread not available for this ruby interpreter"
|
12
|
+
end
|
13
|
+
|
14
|
+
unless defined? ThreadError
|
15
|
+
class ThreadError < StandardError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if $DEBUG
|
20
|
+
Thread.abort_on_exception = true
|
21
|
+
end
|
22
|
+
|
23
|
+
module XThread
|
24
|
+
module MonitorMixin
|
25
|
+
def self.extend_object(obj)
|
26
|
+
super(obj)
|
27
|
+
obj.__send__(:mon_initialize)
|
28
|
+
end
|
29
|
+
|
30
|
+
def mon_initialize
|
31
|
+
@_monitor = Monitor.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def mon_try_enter
|
35
|
+
@_monitor.try_enter
|
36
|
+
end
|
37
|
+
|
38
|
+
def mon_enter
|
39
|
+
@_monitor.enter
|
40
|
+
end
|
41
|
+
|
42
|
+
def mon_exit
|
43
|
+
@_monitor.exit
|
44
|
+
end
|
45
|
+
|
46
|
+
def mon_synchronize(&block)
|
47
|
+
@_monitor.synchronize(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def new_cond
|
51
|
+
@_monitor.new_cond
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module XThread
|
58
|
+
class RBQueue
|
59
|
+
def initialize
|
60
|
+
@que = []
|
61
|
+
@que.taint # enable tainted comunication
|
62
|
+
self.taint
|
63
|
+
@mutex = Mutex.new
|
64
|
+
@cond = XThread::ConditionVariable.new
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Pushes +obj+ to the queue.
|
69
|
+
#
|
70
|
+
def push(obj)
|
71
|
+
@mutex.synchronize do
|
72
|
+
@que.push obj
|
73
|
+
@cond.signal
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Alias of push
|
79
|
+
#
|
80
|
+
alias << push
|
81
|
+
|
82
|
+
#
|
83
|
+
# Alias of push
|
84
|
+
#
|
85
|
+
alias enq push
|
86
|
+
|
87
|
+
#
|
88
|
+
# Retrieves data from the queue. If the queue is empty, the calling thread is
|
89
|
+
# suspended until data is pushed onto the queue. If +non_block+ is true, the
|
90
|
+
# thread isn't suspended, and an exception is raised.
|
91
|
+
#
|
92
|
+
def pop(non_block=false)
|
93
|
+
@mutex.synchronize{
|
94
|
+
while true
|
95
|
+
if @que.empty?
|
96
|
+
@cond.wait(@mutex)
|
97
|
+
else
|
98
|
+
return @que.shift
|
99
|
+
end
|
100
|
+
end
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Alias of pop
|
106
|
+
#
|
107
|
+
alias shift pop
|
108
|
+
|
109
|
+
#
|
110
|
+
# Alias of pop
|
111
|
+
#
|
112
|
+
alias deq pop
|
113
|
+
|
114
|
+
#
|
115
|
+
# Returns +true+ if the queue is empty.
|
116
|
+
#
|
117
|
+
def empty?
|
118
|
+
@que.empty?
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Removes all objects from the queue.
|
123
|
+
#
|
124
|
+
def clear
|
125
|
+
@que.clear
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# Returns the length of the queue.
|
130
|
+
#
|
131
|
+
def length
|
132
|
+
@que.length
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Alias of length.
|
137
|
+
#
|
138
|
+
alias size length
|
139
|
+
|
140
|
+
#
|
141
|
+
# Returns the number of threads waiting on the queue.
|
142
|
+
#
|
143
|
+
# def num_waiting
|
144
|
+
# @waiting.size
|
145
|
+
# end
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# This class represents queues of specified size capacity. The push operation
|
150
|
+
# may be blocked if the capacity is full.
|
151
|
+
#
|
152
|
+
# See Queue for an example of how a SizedQueue works.
|
153
|
+
#
|
154
|
+
class RBSizedQueue < RBQueue
|
155
|
+
#
|
156
|
+
# Creates a fixed-length queue with a maximum size of +max+.
|
157
|
+
#
|
158
|
+
def initialize(max)
|
159
|
+
raise ArgumentError, "queue size must be positive" unless max > 0
|
160
|
+
@max = max
|
161
|
+
@cond_wait = ConditionVariable.new
|
162
|
+
super()
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Returns the maximum size of the queue.
|
167
|
+
#
|
168
|
+
def max
|
169
|
+
@max
|
170
|
+
end
|
171
|
+
|
172
|
+
#
|
173
|
+
# Sets the maximum size of the queue.
|
174
|
+
#
|
175
|
+
def max=(max)
|
176
|
+
diff = nil
|
177
|
+
@mutex.synchronize {
|
178
|
+
if max <= @max
|
179
|
+
@max = max
|
180
|
+
else
|
181
|
+
diff = max - @max
|
182
|
+
@max = max
|
183
|
+
end
|
184
|
+
}
|
185
|
+
if diff
|
186
|
+
diff.times do
|
187
|
+
@cond_wait.signal
|
188
|
+
end
|
189
|
+
end
|
190
|
+
max
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Pushes +obj+ to the queue. If there is no space left in the queue, waits
|
195
|
+
# until space becomes available.
|
196
|
+
#
|
197
|
+
def push(obj)
|
198
|
+
@mutex.synchronize{
|
199
|
+
while true
|
200
|
+
break if @que.length < @max
|
201
|
+
@cond_wait.wait(@mutex)
|
202
|
+
end
|
203
|
+
|
204
|
+
@que.push obj
|
205
|
+
@cond.signal
|
206
|
+
}
|
207
|
+
end
|
208
|
+
|
209
|
+
#
|
210
|
+
# Alias of push
|
211
|
+
#
|
212
|
+
alias << push
|
213
|
+
|
214
|
+
#
|
215
|
+
# Alias of push
|
216
|
+
#
|
217
|
+
alias enq push
|
218
|
+
|
219
|
+
#
|
220
|
+
# Retrieves data from the queue and runs a waiting thread, if any.
|
221
|
+
#
|
222
|
+
def pop(*args)
|
223
|
+
retval = super
|
224
|
+
@mutex.synchronize {
|
225
|
+
if @que.length < @max
|
226
|
+
@cond_wait.signal
|
227
|
+
end
|
228
|
+
}
|
229
|
+
retval
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# Alias of pop
|
234
|
+
#
|
235
|
+
alias shift pop
|
236
|
+
|
237
|
+
#
|
238
|
+
# Alias of pop
|
239
|
+
#
|
240
|
+
alias deq pop
|
241
|
+
|
242
|
+
#
|
243
|
+
# Returns the number of threads waiting on the queue.
|
244
|
+
#
|
245
|
+
# def num_waiting
|
246
|
+
# @waiting.size + @queue_wait.size
|
247
|
+
# end
|
248
|
+
end
|
249
|
+
|
250
|
+
# Documentation comments:
|
251
|
+
# - How do you make RDoc inherit documentation from superclass?
|
252
|
+
end
|
data/monitor.c
ADDED
@@ -0,0 +1,404 @@
|
|
1
|
+
/**********************************************************************
|
2
|
+
|
3
|
+
monitor.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
|
+
VALUE rb_cXThreadMonitor;
|
15
|
+
VALUE rb_cXThreadMonitorCond;
|
16
|
+
|
17
|
+
typedef struct rb_xthread_monitor_struct
|
18
|
+
{
|
19
|
+
VALUE owner;
|
20
|
+
long count;
|
21
|
+
VALUE mutex;
|
22
|
+
} xthread_monitor_t;
|
23
|
+
|
24
|
+
#define GetXThreadMonitorPtr(obj, tobj) \
|
25
|
+
TypedData_Get_Struct((obj), xthread_monitor_t, &xthread_monitor_data_type, (tobj))
|
26
|
+
|
27
|
+
#define XTHREAD_MONITOR_CHECK_OWNER(obj) \
|
28
|
+
{ \
|
29
|
+
xthread_monitor_t *mon; \
|
30
|
+
VALUE th = rb_thread_current(); \
|
31
|
+
GetXThreadMonitorPtr(obj, mon); \
|
32
|
+
if (mon->owner != th) { \
|
33
|
+
rb_raise(rb_eThreadError, "current thread not owner"); \
|
34
|
+
} \
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
static void
|
39
|
+
xthread_monitor_mark(void *ptr)
|
40
|
+
{
|
41
|
+
xthread_monitor_t *mon = (xthread_monitor_t*)ptr;
|
42
|
+
|
43
|
+
rb_gc_mark(mon->owner);
|
44
|
+
rb_gc_mark(mon->mutex);
|
45
|
+
}
|
46
|
+
|
47
|
+
static void
|
48
|
+
xthread_monitor_free(void *ptr)
|
49
|
+
{
|
50
|
+
ruby_xfree(ptr);
|
51
|
+
}
|
52
|
+
|
53
|
+
static size_t
|
54
|
+
xthread_monitor_memsize(const void *ptr)
|
55
|
+
{
|
56
|
+
return ptr ? sizeof(xthread_monitor_t) : 0;
|
57
|
+
}
|
58
|
+
|
59
|
+
static const rb_data_type_t xthread_monitor_data_type = {
|
60
|
+
"xthread_monitor",
|
61
|
+
{xthread_monitor_mark, xthread_monitor_free, xthread_monitor_memsize,},
|
62
|
+
};
|
63
|
+
|
64
|
+
static VALUE
|
65
|
+
xthread_monitor_alloc(VALUE klass)
|
66
|
+
{
|
67
|
+
VALUE volatile obj;
|
68
|
+
xthread_monitor_t *mon;
|
69
|
+
|
70
|
+
obj = TypedData_Make_Struct(klass, xthread_monitor_t, &xthread_monitor_data_type, mon);
|
71
|
+
mon->owner = Qnil;
|
72
|
+
mon->count = 0;
|
73
|
+
mon->mutex = rb_mutex_new();
|
74
|
+
|
75
|
+
return obj;
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE
|
79
|
+
xthread_monitor_initialize(VALUE self)
|
80
|
+
{
|
81
|
+
return self;
|
82
|
+
}
|
83
|
+
|
84
|
+
VALUE
|
85
|
+
rb_xthread_monitor_new(void)
|
86
|
+
{
|
87
|
+
return xthread_monitor_alloc(rb_cXThreadMonitor);
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/*
|
92
|
+
static VALUE
|
93
|
+
rb_xthread_monitor_check_owner(VALUE self)
|
94
|
+
{
|
95
|
+
xthread_monitor_t *mon;
|
96
|
+
VALUE th = rb_thread_current();
|
97
|
+
|
98
|
+
GetXThreadMonitorPtr(self, mon);
|
99
|
+
|
100
|
+
if (mon->owner != th) {
|
101
|
+
rb_raise(rb_eThreadError, "current thread not owner");
|
102
|
+
}
|
103
|
+
}
|
104
|
+
*/
|
105
|
+
|
106
|
+
VALUE
|
107
|
+
rb_xthread_monitor_valid_owner_p(VALUE self)
|
108
|
+
{
|
109
|
+
xthread_monitor_t *mon;
|
110
|
+
VALUE th = rb_thread_current();
|
111
|
+
|
112
|
+
GetXThreadMonitorPtr(self, mon);
|
113
|
+
|
114
|
+
if (mon->owner == th) {
|
115
|
+
return Qtrue;
|
116
|
+
}
|
117
|
+
else {
|
118
|
+
return Qfalse;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
VALUE
|
123
|
+
rb_xthread_monitor_try_enter(VALUE self)
|
124
|
+
{
|
125
|
+
xthread_monitor_t *mon;
|
126
|
+
VALUE th = rb_thread_current();
|
127
|
+
|
128
|
+
GetXThreadMonitorPtr(self, mon);
|
129
|
+
|
130
|
+
if (mon->owner != th) {
|
131
|
+
if (rb_mutex_trylock(mon->mutex) == Qfalse) {
|
132
|
+
return Qfalse;
|
133
|
+
}
|
134
|
+
mon->owner = th;
|
135
|
+
}
|
136
|
+
mon->count++;
|
137
|
+
return Qtrue;
|
138
|
+
}
|
139
|
+
|
140
|
+
VALUE
|
141
|
+
rb_xthread_monitor_enter(VALUE self)
|
142
|
+
{
|
143
|
+
xthread_monitor_t *mon;
|
144
|
+
VALUE th = rb_thread_current();
|
145
|
+
|
146
|
+
GetXThreadMonitorPtr(self, mon);
|
147
|
+
if (mon->owner != th) {
|
148
|
+
rb_mutex_lock(mon->mutex);
|
149
|
+
mon->owner = th;
|
150
|
+
}
|
151
|
+
mon->count += 1;
|
152
|
+
}
|
153
|
+
|
154
|
+
VALUE
|
155
|
+
rb_xthread_monitor_exit(VALUE self)
|
156
|
+
{
|
157
|
+
xthread_monitor_t *mon;
|
158
|
+
VALUE th = rb_thread_current();
|
159
|
+
|
160
|
+
GetXThreadMonitorPtr(self, mon);
|
161
|
+
|
162
|
+
XTHREAD_MONITOR_CHECK_OWNER(self);
|
163
|
+
mon->count--;
|
164
|
+
if(mon->count == 0) {
|
165
|
+
mon->owner = Qnil;
|
166
|
+
rb_mutex_unlock(mon->mutex);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
VALUE
|
171
|
+
rb_xthread_monitor_synchronize(VALUE self, VALUE (*func)(VALUE arg), VALUE arg)
|
172
|
+
{
|
173
|
+
rb_xthread_monitor_enter(self);
|
174
|
+
return rb_ensure(func, arg, rb_xthread_monitor_exit, self);
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE
|
178
|
+
xthread_monitor_synchronize(VALUE self)
|
179
|
+
{
|
180
|
+
return rb_xthread_monitor_synchronize(self, rb_yield, self);
|
181
|
+
}
|
182
|
+
|
183
|
+
VALUE
|
184
|
+
rb_xthread_monitor_new_cond(VALUE self)
|
185
|
+
{
|
186
|
+
rb_xthread_monitor_cond_new(self);
|
187
|
+
}
|
188
|
+
|
189
|
+
VALUE
|
190
|
+
rb_xthread_monitor_enter_for_cond(VALUE self, long count)
|
191
|
+
{
|
192
|
+
xthread_monitor_t *mon;
|
193
|
+
VALUE th = rb_thread_current();
|
194
|
+
|
195
|
+
GetXThreadMonitorPtr(self, mon);
|
196
|
+
|
197
|
+
mon->owner = th;
|
198
|
+
mon->count = count;
|
199
|
+
}
|
200
|
+
|
201
|
+
long
|
202
|
+
rb_xthread_monitor_exit_for_cond(VALUE self)
|
203
|
+
{
|
204
|
+
xthread_monitor_t *mon;
|
205
|
+
long count;
|
206
|
+
|
207
|
+
GetXThreadMonitorPtr(self, mon);
|
208
|
+
|
209
|
+
count = mon->count;
|
210
|
+
mon->owner = Qnil;
|
211
|
+
mon->count = 0;
|
212
|
+
return count;
|
213
|
+
}
|
214
|
+
|
215
|
+
typedef struct rb_xthread_monitor_cond_struct
|
216
|
+
{
|
217
|
+
VALUE monitor;
|
218
|
+
VALUE cond;
|
219
|
+
|
220
|
+
} xthread_monitor_cond_t;
|
221
|
+
|
222
|
+
#define GetXThreadMonitorCondPtr(obj, tobj) \
|
223
|
+
TypedData_Get_Struct((obj), xthread_monitor_cond_t, &xthread_monitor_cond_data_type, (tobj))
|
224
|
+
|
225
|
+
static void
|
226
|
+
xthread_monitor_cond_mark(void *ptr)
|
227
|
+
{
|
228
|
+
xthread_monitor_cond_t *cv = (xthread_monitor_cond_t*)ptr;
|
229
|
+
|
230
|
+
rb_gc_mark(cv->monitor);
|
231
|
+
rb_gc_mark(cv->cond);
|
232
|
+
}
|
233
|
+
|
234
|
+
static void
|
235
|
+
xthread_monitor_cond_free(void *ptr)
|
236
|
+
{
|
237
|
+
ruby_xfree(ptr);
|
238
|
+
}
|
239
|
+
|
240
|
+
static size_t
|
241
|
+
xthread_monitor_cond_memsize(const void *ptr)
|
242
|
+
{
|
243
|
+
return ptr ? sizeof(xthread_monitor_cond_t) : 0;
|
244
|
+
}
|
245
|
+
|
246
|
+
static const rb_data_type_t xthread_monitor_cond_data_type = {
|
247
|
+
"xthread_monitor_cond",
|
248
|
+
{xthread_monitor_cond_mark, xthread_monitor_cond_free, xthread_monitor_cond_memsize,},
|
249
|
+
};
|
250
|
+
|
251
|
+
static VALUE
|
252
|
+
xthread_monitor_cond_alloc(VALUE klass)
|
253
|
+
{
|
254
|
+
VALUE volatile obj;
|
255
|
+
xthread_monitor_cond_t *cv;
|
256
|
+
|
257
|
+
obj = TypedData_Make_Struct(klass,
|
258
|
+
xthread_monitor_cond_t, &xthread_monitor_cond_data_type, cv);
|
259
|
+
|
260
|
+
cv->monitor = Qnil;
|
261
|
+
cv->cond = rb_xthread_cond_new();
|
262
|
+
return obj;
|
263
|
+
}
|
264
|
+
|
265
|
+
static VALUE
|
266
|
+
xthread_monitor_cond_initialize(VALUE self, VALUE mon)
|
267
|
+
{
|
268
|
+
xthread_monitor_cond_t *cv;
|
269
|
+
GetXThreadMonitorCondPtr(self, cv);
|
270
|
+
|
271
|
+
cv->monitor = mon;
|
272
|
+
return self;
|
273
|
+
}
|
274
|
+
|
275
|
+
VALUE
|
276
|
+
rb_xthread_monitor_cond_new(VALUE mon)
|
277
|
+
{
|
278
|
+
VALUE self;
|
279
|
+
|
280
|
+
self = xthread_monitor_cond_alloc(rb_cXThreadMonitorCond);
|
281
|
+
xthread_monitor_cond_initialize(self, mon);
|
282
|
+
return self;
|
283
|
+
}
|
284
|
+
|
285
|
+
struct xthread_monitor_cond_wait_arg {
|
286
|
+
VALUE cond;
|
287
|
+
VALUE monitor;
|
288
|
+
VALUE timeout;
|
289
|
+
long count;
|
290
|
+
};
|
291
|
+
|
292
|
+
static VALUE
|
293
|
+
rb_xthread_monitor_cond_wait_cond(struct xthread_monitor_cond_wait_arg *arg)
|
294
|
+
{
|
295
|
+
xthread_monitor_t *mon;
|
296
|
+
VALUE v_mon = arg->monitor;
|
297
|
+
GetXThreadMonitorPtr(v_mon, mon);
|
298
|
+
|
299
|
+
rb_xthread_cond_wait(arg->cond, mon->mutex, arg->timeout);
|
300
|
+
return Qtrue;
|
301
|
+
}
|
302
|
+
|
303
|
+
static VALUE
|
304
|
+
rb_xthread_monitor_cond_wait_enter(struct xthread_monitor_cond_wait_arg *arg)
|
305
|
+
{
|
306
|
+
rb_xthread_monitor_enter_for_cond(arg->monitor, arg->count);
|
307
|
+
}
|
308
|
+
|
309
|
+
VALUE
|
310
|
+
rb_xthread_monitor_cond_wait(VALUE self, VALUE timeout)
|
311
|
+
{
|
312
|
+
xthread_monitor_cond_t *cv;
|
313
|
+
struct xthread_monitor_cond_wait_arg arg;
|
314
|
+
|
315
|
+
GetXThreadMonitorCondPtr(self, cv);
|
316
|
+
|
317
|
+
XTHREAD_MONITOR_CHECK_OWNER(cv->monitor);
|
318
|
+
arg.cond = cv->cond;
|
319
|
+
arg.monitor = cv->monitor;
|
320
|
+
arg.timeout = timeout;
|
321
|
+
arg.count = rb_xthread_monitor_exit_for_cond(cv->monitor);
|
322
|
+
|
323
|
+
return rb_ensure(rb_xthread_monitor_cond_wait_cond, (VALUE)&arg,
|
324
|
+
rb_xthread_monitor_cond_wait_enter, (VALUE)&arg);
|
325
|
+
}
|
326
|
+
|
327
|
+
static VALUE
|
328
|
+
xthread_monitor_cond_wait(int argc, VALUE *argv, VALUE self)
|
329
|
+
{
|
330
|
+
VALUE timeout;
|
331
|
+
|
332
|
+
rb_scan_args(argc, argv, "01", &timeout);
|
333
|
+
return rb_xthread_monitor_cond_wait(self, timeout);
|
334
|
+
}
|
335
|
+
|
336
|
+
VALUE
|
337
|
+
rb_xthread_monitor_cond_wait_while(VALUE self)
|
338
|
+
{
|
339
|
+
while (RTEST(rb_yield)) {
|
340
|
+
rb_xthread_monitor_cond_wait(self, Qnil);
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
VALUE
|
345
|
+
rb_xthread_monitor_cond_wait_until(VALUE self)
|
346
|
+
{
|
347
|
+
while (!RTEST(rb_yield)) {
|
348
|
+
rb_xthread_monitor_cond_wait(self, Qnil);
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
VALUE
|
353
|
+
rb_xthread_monitor_cond_signal(VALUE self)
|
354
|
+
{
|
355
|
+
xthread_monitor_cond_t *cv;
|
356
|
+
GetXThreadMonitorCondPtr(self, cv);
|
357
|
+
|
358
|
+
XTHREAD_MONITOR_CHECK_OWNER(cv->monitor);
|
359
|
+
rb_xthread_cond_signal(cv->cond);
|
360
|
+
}
|
361
|
+
|
362
|
+
VALUE
|
363
|
+
rb_xthread_monitor_cond_broadcast(VALUE self)
|
364
|
+
{
|
365
|
+
xthread_monitor_cond_t *cv;
|
366
|
+
GetXThreadMonitorCondPtr(self, cv);
|
367
|
+
|
368
|
+
XTHREAD_MONITOR_CHECK_OWNER(cv->monitor);
|
369
|
+
rb_xthread_cond_broadcast(cv->cond);
|
370
|
+
}
|
371
|
+
|
372
|
+
void
|
373
|
+
Init_XThreadMonitor(void)
|
374
|
+
{
|
375
|
+
rb_cXThreadMonitor =
|
376
|
+
rb_define_class_under(rb_mXThread, "Monitor", rb_cObject);
|
377
|
+
rb_define_alloc_func(rb_cXThreadMonitor, xthread_monitor_alloc);
|
378
|
+
rb_define_method(rb_cXThreadMonitor, "initialize", xthread_monitor_initialize, 0);
|
379
|
+
rb_define_method(rb_cXThreadMonitor, "try_enter", rb_xthread_monitor_try_enter, 0);
|
380
|
+
rb_define_method(rb_cXThreadMonitor, "enter", rb_xthread_monitor_enter, 0);
|
381
|
+
rb_define_method(rb_cXThreadMonitor, "exit", rb_xthread_monitor_exit, 0);
|
382
|
+
rb_define_method(rb_cXThreadMonitor, "synchronize", xthread_monitor_synchronize, 0);
|
383
|
+
rb_define_method(rb_cXThreadMonitor, "new_cond", rb_xthread_monitor_new_cond, 0);
|
384
|
+
rb_define_method(rb_cXThreadMonitor, "synchronize", xthread_monitor_synchronize, 0);
|
385
|
+
|
386
|
+
rb_cXThreadMonitorCond =
|
387
|
+
rb_define_class_under(rb_cXThreadMonitor, "ConditionVariable", rb_cObject);
|
388
|
+
rb_define_alloc_func(rb_cXThreadMonitorCond, xthread_monitor_cond_alloc);
|
389
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
390
|
+
"initialize", xthread_monitor_cond_initialize, 0);
|
391
|
+
|
392
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
393
|
+
"wait", xthread_monitor_cond_wait, -1);
|
394
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
395
|
+
"wait_while", rb_xthread_monitor_cond_wait_while, 0);
|
396
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
397
|
+
"wait_until", rb_xthread_monitor_cond_wait_until, 0);
|
398
|
+
|
399
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
400
|
+
"signal", rb_xthread_monitor_cond_signal, 0);
|
401
|
+
rb_define_method(rb_cXThreadMonitorCond,
|
402
|
+
"broadcast", rb_xthread_monitor_cond_broadcast, 0);
|
403
|
+
|
404
|
+
}
|