polyphony 0.40 → 0.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +11 -2
- data/.gitignore +2 -2
- data/.rubocop.yml +30 -0
- data/CHANGELOG.md +6 -2
- data/Gemfile.lock +9 -6
- data/Rakefile +2 -2
- data/TODO.md +18 -97
- data/docs/_includes/head.html +40 -0
- data/docs/_includes/nav.html +5 -5
- data/docs/api-reference/fiber.md +2 -2
- data/docs/main-concepts/design-principles.md +67 -9
- data/docs/main-concepts/extending.md +1 -1
- data/examples/core/xx-agent.rb +102 -0
- data/examples/core/xx-sleeping.rb +14 -6
- data/examples/io/xx-irb.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +14 -25
- data/ext/{gyro → polyphony}/extconf.rb +2 -2
- data/ext/{gyro → polyphony}/fiber.c +15 -19
- data/ext/{gyro → polyphony}/libev.c +0 -0
- data/ext/{gyro → polyphony}/libev.h +0 -0
- data/ext/polyphony/libev_agent.c +503 -0
- data/ext/polyphony/libev_queue.c +214 -0
- data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -25
- data/ext/polyphony/polyphony.h +90 -0
- data/ext/polyphony/polyphony_ext.c +23 -0
- data/ext/{gyro → polyphony}/socket.c +14 -14
- data/ext/{gyro → polyphony}/thread.c +32 -115
- data/ext/{gyro → polyphony}/tracing.c +1 -1
- data/lib/polyphony.rb +16 -12
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/adapters/postgres.rb +6 -5
- data/lib/polyphony/adapters/process.rb +5 -5
- data/lib/polyphony/adapters/trace.rb +28 -28
- data/lib/polyphony/core/channel.rb +3 -3
- data/lib/polyphony/core/exceptions.rb +1 -1
- data/lib/polyphony/core/global_api.rb +11 -9
- data/lib/polyphony/core/resource_pool.rb +3 -3
- data/lib/polyphony/core/sync.rb +2 -2
- data/lib/polyphony/core/thread_pool.rb +6 -6
- data/lib/polyphony/core/throttler.rb +13 -6
- data/lib/polyphony/event.rb +27 -0
- data/lib/polyphony/extensions/core.rb +20 -11
- data/lib/polyphony/extensions/fiber.rb +4 -4
- data/lib/polyphony/extensions/io.rb +56 -26
- data/lib/polyphony/extensions/openssl.rb +4 -8
- data/lib/polyphony/extensions/socket.rb +27 -9
- data/lib/polyphony/extensions/thread.rb +16 -9
- data/lib/polyphony/net.rb +9 -9
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +2 -2
- data/test/helper.rb +12 -1
- data/test/test_agent.rb +77 -0
- data/test/{test_async.rb → test_event.rb} +13 -7
- data/test/test_ext.rb +25 -4
- data/test/test_fiber.rb +19 -10
- data/test/test_global_api.rb +4 -4
- data/test/test_io.rb +46 -24
- data/test/test_queue.rb +74 -0
- data/test/test_signal.rb +3 -40
- data/test/test_socket.rb +33 -0
- data/test/test_thread.rb +37 -16
- data/test/test_trace.rb +6 -5
- metadata +24 -24
- data/ext/gyro/async.c +0 -132
- data/ext/gyro/child.c +0 -108
- data/ext/gyro/gyro.h +0 -158
- data/ext/gyro/gyro_ext.c +0 -33
- data/ext/gyro/io.c +0 -457
- data/ext/gyro/queue.c +0 -146
- data/ext/gyro/selector.c +0 -205
- data/ext/gyro/signal.c +0 -99
- data/ext/gyro/timer.c +0 -115
- data/test/test_timer.rb +0 -56
data/ext/gyro/queue.c
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
#include "gyro.h"
|
2
|
-
|
3
|
-
typedef struct queue {
|
4
|
-
VALUE items;
|
5
|
-
VALUE shift_waiters;
|
6
|
-
} Gyro_Queue_t;
|
7
|
-
|
8
|
-
VALUE cGyro_Queue = Qnil;
|
9
|
-
|
10
|
-
static void Gyro_Queue_mark(void *ptr) {
|
11
|
-
Gyro_Queue_t *queue = ptr;
|
12
|
-
if (queue->items != Qnil) {
|
13
|
-
rb_gc_mark(queue->items);
|
14
|
-
}
|
15
|
-
if (queue->shift_waiters != Qnil) {
|
16
|
-
rb_gc_mark(queue->shift_waiters);
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
static size_t Gyro_Queue_size(const void *ptr) {
|
21
|
-
return sizeof(Gyro_Queue_t);
|
22
|
-
}
|
23
|
-
|
24
|
-
static const rb_data_type_t Gyro_Queue_type = {
|
25
|
-
"Gyro_Queue",
|
26
|
-
{Gyro_Queue_mark, RUBY_DEFAULT_FREE, Gyro_Queue_size,},
|
27
|
-
0, 0, 0
|
28
|
-
};
|
29
|
-
|
30
|
-
static VALUE Gyro_Queue_allocate(VALUE klass) {
|
31
|
-
Gyro_Queue_t *queue;
|
32
|
-
// return Data_Make_Struct(klass, Gyro_Queue_t, Gyro_Queue_mark, free, queue);
|
33
|
-
|
34
|
-
queue = ALLOC(Gyro_Queue_t);
|
35
|
-
// struct Gyro_Queue *queue = ALLOC(struct Gyro_Queue);
|
36
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
|
37
|
-
}
|
38
|
-
|
39
|
-
#define GetGyro_Queue(obj, queue) \
|
40
|
-
TypedData_Get_Struct((obj), Gyro_Queue_t, &Gyro_Queue_type, (queue))
|
41
|
-
|
42
|
-
static VALUE Gyro_Queue_initialize(VALUE self) {
|
43
|
-
Gyro_Queue_t *queue;
|
44
|
-
GetGyro_Queue(self, queue);
|
45
|
-
|
46
|
-
queue->items = rb_ary_new();
|
47
|
-
queue->shift_waiters = rb_ary_new();
|
48
|
-
|
49
|
-
return self;
|
50
|
-
}
|
51
|
-
|
52
|
-
VALUE Gyro_Queue_push(VALUE self, VALUE value) {
|
53
|
-
Gyro_Queue_t *queue;
|
54
|
-
GetGyro_Queue(self, queue);
|
55
|
-
|
56
|
-
if (RARRAY_LEN(queue->shift_waiters) > 0) {
|
57
|
-
VALUE async = rb_ary_shift(queue->shift_waiters);
|
58
|
-
rb_funcall(async, ID_signal, 1, Qnil);
|
59
|
-
}
|
60
|
-
|
61
|
-
rb_ary_push(queue->items, value);
|
62
|
-
return self;
|
63
|
-
}
|
64
|
-
|
65
|
-
VALUE Gyro_Queue_shift(VALUE self) {
|
66
|
-
Gyro_Queue_t *queue;
|
67
|
-
GetGyro_Queue(self, queue);
|
68
|
-
|
69
|
-
if (RARRAY_LEN(queue->items) == 0) {
|
70
|
-
VALUE ret;
|
71
|
-
VALUE async = Fiber_auto_async(rb_fiber_current());
|
72
|
-
rb_ary_push(queue->shift_waiters, async);
|
73
|
-
ret = Gyro_Async_await_no_raise(async);
|
74
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
75
|
-
rb_ary_delete(queue->shift_waiters, async);
|
76
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
77
|
-
}
|
78
|
-
RB_GC_GUARD(ret);
|
79
|
-
}
|
80
|
-
|
81
|
-
return rb_ary_shift(queue->items);
|
82
|
-
}
|
83
|
-
|
84
|
-
VALUE Gyro_Queue_shift_no_wait(VALUE self) {
|
85
|
-
Gyro_Queue_t *queue;
|
86
|
-
GetGyro_Queue(self, queue);
|
87
|
-
|
88
|
-
return rb_ary_shift(queue->items);
|
89
|
-
}
|
90
|
-
|
91
|
-
VALUE Gyro_Queue_shift_each(VALUE self) {
|
92
|
-
Gyro_Queue_t *queue;
|
93
|
-
VALUE old_queue;
|
94
|
-
GetGyro_Queue(self, queue);
|
95
|
-
old_queue = queue->items;
|
96
|
-
queue->items = rb_ary_new();
|
97
|
-
|
98
|
-
if (rb_block_given_p()) {
|
99
|
-
long len = RARRAY_LEN(old_queue);
|
100
|
-
long i;
|
101
|
-
for (i = 0; i < len; i++) {
|
102
|
-
rb_yield(RARRAY_AREF(old_queue, i));
|
103
|
-
}
|
104
|
-
RB_GC_GUARD(old_queue);
|
105
|
-
return self;
|
106
|
-
}
|
107
|
-
else {
|
108
|
-
RB_GC_GUARD(old_queue);
|
109
|
-
return old_queue;
|
110
|
-
}
|
111
|
-
}
|
112
|
-
|
113
|
-
VALUE Gyro_Queue_clear(VALUE self) {
|
114
|
-
Gyro_Queue_t *queue;
|
115
|
-
GetGyro_Queue(self, queue);
|
116
|
-
|
117
|
-
rb_ary_clear(queue->items);
|
118
|
-
return self;
|
119
|
-
}
|
120
|
-
|
121
|
-
VALUE Gyro_Queue_empty_p(VALUE self) {
|
122
|
-
Gyro_Queue_t *queue;
|
123
|
-
GetGyro_Queue(self, queue);
|
124
|
-
|
125
|
-
return (RARRAY_LEN(queue->items) == 0) ? Qtrue : Qfalse;
|
126
|
-
}
|
127
|
-
|
128
|
-
void Init_Gyro_Queue() {
|
129
|
-
cGyro_Queue = rb_define_class_under(mGyro, "Queue", rb_cData);
|
130
|
-
rb_define_alloc_func(cGyro_Queue, Gyro_Queue_allocate);
|
131
|
-
|
132
|
-
rb_define_method(cGyro_Queue, "initialize", Gyro_Queue_initialize, 0);
|
133
|
-
rb_define_method(cGyro_Queue, "push", Gyro_Queue_push, 1);
|
134
|
-
rb_define_method(cGyro_Queue, "<<", Gyro_Queue_push, 1);
|
135
|
-
|
136
|
-
rb_define_method(cGyro_Queue, "pop", Gyro_Queue_shift, 0);
|
137
|
-
rb_define_method(cGyro_Queue, "shift", Gyro_Queue_shift, 0);
|
138
|
-
|
139
|
-
rb_define_method(cGyro_Queue, "shift_no_wait", Gyro_Queue_shift_no_wait, 0);
|
140
|
-
|
141
|
-
rb_define_method(cGyro_Queue, "shift_each", Gyro_Queue_shift_each, 0);
|
142
|
-
rb_define_method(cGyro_Queue, "clear", Gyro_Queue_clear, 0);
|
143
|
-
rb_define_method(cGyro_Queue, "empty?", Gyro_Queue_empty_p, 0);
|
144
|
-
}
|
145
|
-
|
146
|
-
|
data/ext/gyro/selector.c
DELETED
@@ -1,205 +0,0 @@
|
|
1
|
-
#include "gyro.h"
|
2
|
-
|
3
|
-
struct Gyro_Selector {
|
4
|
-
struct ev_loop *ev_loop;
|
5
|
-
long run_no_wait_count;
|
6
|
-
int ev_loop_running;
|
7
|
-
struct ev_async async;
|
8
|
-
VALUE active_watchers;
|
9
|
-
};
|
10
|
-
|
11
|
-
VALUE cGyro_Selector = Qnil;
|
12
|
-
|
13
|
-
static void Gyro_Selector_mark(void *ptr) {
|
14
|
-
struct Gyro_Selector *selector = ptr;
|
15
|
-
rb_gc_mark(selector->active_watchers);
|
16
|
-
}
|
17
|
-
|
18
|
-
static void Gyro_Selector_free(void *ptr) {
|
19
|
-
struct Gyro_Selector *selector = ptr;
|
20
|
-
ev_async_stop(selector->ev_loop, &selector->async);
|
21
|
-
if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
|
22
|
-
ev_loop_destroy(selector->ev_loop);
|
23
|
-
}
|
24
|
-
xfree(selector);
|
25
|
-
}
|
26
|
-
|
27
|
-
static size_t Gyro_Selector_size(const void *ptr) {
|
28
|
-
return sizeof(struct Gyro_Selector);
|
29
|
-
}
|
30
|
-
|
31
|
-
static const rb_data_type_t Gyro_Selector_type = {
|
32
|
-
"Gyro_Selector",
|
33
|
-
{Gyro_Selector_mark, Gyro_Selector_free, Gyro_Selector_size,},
|
34
|
-
0, 0, 0
|
35
|
-
};
|
36
|
-
|
37
|
-
static VALUE Gyro_Selector_allocate(VALUE klass) {
|
38
|
-
struct Gyro_Selector *selector = ALLOC(struct Gyro_Selector);
|
39
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Selector_type, selector);
|
40
|
-
}
|
41
|
-
|
42
|
-
#define GetGyro_Selector(obj, selector) \
|
43
|
-
TypedData_Get_Struct((obj), struct Gyro_Selector, &Gyro_Selector_type, (selector))
|
44
|
-
|
45
|
-
inline struct ev_loop *Gyro_Selector_ev_loop(VALUE self) {
|
46
|
-
struct Gyro_Selector *selector;
|
47
|
-
GetGyro_Selector(self, selector);
|
48
|
-
|
49
|
-
return selector->ev_loop;
|
50
|
-
}
|
51
|
-
|
52
|
-
inline struct ev_loop *Gyro_Selector_current_thread_ev_loop() {
|
53
|
-
struct Gyro_Selector *selector;
|
54
|
-
GetGyro_Selector(Thread_current_event_selector(), selector);
|
55
|
-
|
56
|
-
return selector->ev_loop;
|
57
|
-
}
|
58
|
-
|
59
|
-
inline ev_tstamp Gyro_Selector_now(VALUE self) {
|
60
|
-
struct Gyro_Selector *selector;
|
61
|
-
GetGyro_Selector(self, selector);
|
62
|
-
|
63
|
-
return ev_now(selector->ev_loop);
|
64
|
-
}
|
65
|
-
|
66
|
-
long Gyro_Selector_pending_count(VALUE self) {
|
67
|
-
struct Gyro_Selector *selector;
|
68
|
-
GetGyro_Selector(self, selector);
|
69
|
-
|
70
|
-
return ev_pending_count(selector->ev_loop);
|
71
|
-
}
|
72
|
-
|
73
|
-
void dummy_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
|
74
|
-
// This callback does nothing, the selector's async is used solely for waking
|
75
|
-
// up the event loop.
|
76
|
-
}
|
77
|
-
|
78
|
-
inline void Gyro_Selector_run_ev_loop(struct Gyro_Selector *selector, int flags) {
|
79
|
-
selector->ev_loop_running = 1;
|
80
|
-
ev_run(selector->ev_loop, flags);
|
81
|
-
selector->ev_loop_running = 0;
|
82
|
-
}
|
83
|
-
|
84
|
-
static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
|
85
|
-
struct Gyro_Selector *selector;
|
86
|
-
GetGyro_Selector(self, selector);
|
87
|
-
|
88
|
-
int use_default_loop = (rb_thread_current() == rb_thread_main());
|
89
|
-
selector->ev_loop = use_default_loop ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
|
90
|
-
selector->run_no_wait_count = 0;
|
91
|
-
|
92
|
-
selector->active_watchers = rb_hash_new();
|
93
|
-
|
94
|
-
ev_async_init(&selector->async, dummy_async_callback);
|
95
|
-
ev_async_start(selector->ev_loop, &selector->async);
|
96
|
-
Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
|
97
|
-
return Qnil;
|
98
|
-
}
|
99
|
-
|
100
|
-
inline void Gyro_Selector_add_active_watcher(VALUE self, VALUE watcher) {
|
101
|
-
struct Gyro_Selector *selector;
|
102
|
-
GetGyro_Selector(self, selector);
|
103
|
-
|
104
|
-
rb_hash_aset(selector->active_watchers, watcher, Qtrue);
|
105
|
-
}
|
106
|
-
|
107
|
-
inline void Gyro_Selector_remove_active_watcher(VALUE self, VALUE watcher) {
|
108
|
-
struct Gyro_Selector *selector;
|
109
|
-
GetGyro_Selector(self, selector);
|
110
|
-
|
111
|
-
rb_hash_delete(selector->active_watchers, watcher);
|
112
|
-
}
|
113
|
-
|
114
|
-
inline VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber) {
|
115
|
-
struct Gyro_Selector *selector;
|
116
|
-
GetGyro_Selector(self, selector);
|
117
|
-
if (selector->ev_loop) {
|
118
|
-
selector->run_no_wait_count = 0;
|
119
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
120
|
-
Gyro_Selector_run_ev_loop(selector, EVRUN_ONCE);
|
121
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
122
|
-
}
|
123
|
-
return Qnil;
|
124
|
-
}
|
125
|
-
|
126
|
-
inline void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runnable_count) {
|
127
|
-
struct Gyro_Selector *selector;
|
128
|
-
GetGyro_Selector(self, selector);
|
129
|
-
|
130
|
-
selector->run_no_wait_count++;
|
131
|
-
if (selector->run_no_wait_count < runnable_count || selector->run_no_wait_count < 10) {
|
132
|
-
return;
|
133
|
-
}
|
134
|
-
|
135
|
-
selector->run_no_wait_count = 0;
|
136
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
137
|
-
Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
|
138
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
139
|
-
}
|
140
|
-
|
141
|
-
VALUE Gyro_Selector_stop(VALUE self) {
|
142
|
-
struct Gyro_Selector *selector;
|
143
|
-
GetGyro_Selector(self, selector);
|
144
|
-
|
145
|
-
if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
|
146
|
-
// ev_loop_destroy(selector->ev_loop);
|
147
|
-
// selector->ev_loop = 0;
|
148
|
-
}
|
149
|
-
return Qnil;
|
150
|
-
}
|
151
|
-
|
152
|
-
VALUE Gyro_Selector_post_fork(VALUE self) {
|
153
|
-
struct Gyro_Selector *selector;
|
154
|
-
GetGyro_Selector(self, selector);
|
155
|
-
|
156
|
-
ev_loop_fork(selector->ev_loop);
|
157
|
-
return self;
|
158
|
-
}
|
159
|
-
|
160
|
-
VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self) {
|
161
|
-
struct Gyro_Selector *selector;
|
162
|
-
GetGyro_Selector(self, selector);
|
163
|
-
|
164
|
-
if (selector->ev_loop_running) {
|
165
|
-
// Since the loop will run until at least one event has occurred, we signal
|
166
|
-
// the selector's associated async watcher, which will cause the ev loop to
|
167
|
-
// return. In contrast to using `ev_break` to break out of the loop, which
|
168
|
-
// should be called from the same thread (from within the ev_loop), using an
|
169
|
-
// `ev_async` allows us to interrupt the event loop across threads.
|
170
|
-
ev_async_send(selector->ev_loop, &selector->async);
|
171
|
-
return Qtrue;
|
172
|
-
}
|
173
|
-
|
174
|
-
return Qnil;
|
175
|
-
}
|
176
|
-
|
177
|
-
inline static VALUE Gyro_Selector_wait_readable(VALUE self, VALUE io) {
|
178
|
-
VALUE watcher = IO_read_watcher(io);
|
179
|
-
return Gyro_IO_await(watcher);
|
180
|
-
}
|
181
|
-
|
182
|
-
inline static VALUE Gyro_Selector_wait_writable(VALUE self, VALUE io) {
|
183
|
-
VALUE watcher = IO_write_watcher(io);
|
184
|
-
return Gyro_IO_await(watcher);
|
185
|
-
}
|
186
|
-
|
187
|
-
inline static VALUE Gyro_Selector_wait_timeout(VALUE self, VALUE duration) {
|
188
|
-
VALUE watcher = rb_funcall(cGyro_Timer, ID_new, 2, duration, Qnil);
|
189
|
-
VALUE ret = Gyro_Timer_await(watcher);
|
190
|
-
RB_GC_GUARD(watcher);
|
191
|
-
return ret;
|
192
|
-
}
|
193
|
-
|
194
|
-
void Init_Gyro_Selector() {
|
195
|
-
cGyro_Selector = rb_define_class_under(mGyro, "Selector", rb_cData);
|
196
|
-
rb_define_alloc_func(cGyro_Selector, Gyro_Selector_allocate);
|
197
|
-
|
198
|
-
rb_define_method(cGyro_Selector, "initialize", Gyro_Selector_initialize, 1);
|
199
|
-
rb_define_method(cGyro_Selector, "run", Gyro_Selector_run, 1);
|
200
|
-
rb_define_method(cGyro_Selector, "stop", Gyro_Selector_stop, 0);
|
201
|
-
rb_define_method(cGyro_Selector, "wait_readable", Gyro_Selector_wait_readable, 1);
|
202
|
-
rb_define_method(cGyro_Selector, "wait_writable", Gyro_Selector_wait_writable, 1);
|
203
|
-
rb_define_method(cGyro_Selector, "wait_timeout", Gyro_Selector_wait_timeout, 1);
|
204
|
-
rb_define_method(cGyro_Selector, "break_out_of_ev_loop", Gyro_Selector_break_out_of_ev_loop, 0);
|
205
|
-
}
|
data/ext/gyro/signal.c
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
#include "gyro.h"
|
2
|
-
|
3
|
-
struct Gyro_Signal {
|
4
|
-
GYRO_WATCHER_DECL(ev_signal);
|
5
|
-
int signum;
|
6
|
-
};
|
7
|
-
|
8
|
-
static VALUE cGyro_Signal = Qnil;
|
9
|
-
|
10
|
-
static void Gyro_Signal_mark(void *ptr) {
|
11
|
-
struct Gyro_Signal *signal = ptr;
|
12
|
-
GYRO_WATCHER_MARK(signal);
|
13
|
-
}
|
14
|
-
|
15
|
-
static void Gyro_Signal_free(void *ptr) {
|
16
|
-
struct Gyro_Signal *signal = ptr;
|
17
|
-
GYRO_WATCHER_FREE(signal);
|
18
|
-
}
|
19
|
-
|
20
|
-
static size_t Gyro_Signal_size(const void *ptr) {
|
21
|
-
return sizeof(struct Gyro_Signal);
|
22
|
-
}
|
23
|
-
|
24
|
-
static const rb_data_type_t Gyro_Signal_type = {
|
25
|
-
"Gyro_Signal",
|
26
|
-
{Gyro_Signal_mark, Gyro_Signal_free, Gyro_Signal_size,},
|
27
|
-
0, 0, 0
|
28
|
-
};
|
29
|
-
|
30
|
-
static VALUE Gyro_Signal_allocate(VALUE klass) {
|
31
|
-
struct Gyro_Signal *signal = ALLOC(struct Gyro_Signal);
|
32
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Signal_type, signal);
|
33
|
-
}
|
34
|
-
|
35
|
-
inline void signal_activate(struct Gyro_Signal *signal) {
|
36
|
-
if (signal->active) return;
|
37
|
-
|
38
|
-
signal->active = 1;
|
39
|
-
signal->fiber = rb_fiber_current();
|
40
|
-
signal->selector = Thread_current_event_selector();
|
41
|
-
signal->ev_loop = Gyro_Selector_ev_loop(signal->selector);
|
42
|
-
Gyro_Selector_add_active_watcher(signal->selector, signal->self);
|
43
|
-
ev_signal_start(signal->ev_loop, &signal->ev_signal);
|
44
|
-
}
|
45
|
-
|
46
|
-
inline void signal_deactivate(struct Gyro_Signal *signal) {
|
47
|
-
if (!signal->active) return;
|
48
|
-
|
49
|
-
ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
50
|
-
Gyro_Selector_remove_active_watcher(signal->selector, signal->self);
|
51
|
-
signal->active = 0;
|
52
|
-
signal->ev_loop = 0;
|
53
|
-
signal->selector = Qnil;
|
54
|
-
signal->fiber = Qnil;
|
55
|
-
}
|
56
|
-
|
57
|
-
void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
|
58
|
-
struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
|
59
|
-
|
60
|
-
Fiber_make_runnable(signal->fiber, INT2NUM(signal->signum));
|
61
|
-
signal_deactivate(signal);
|
62
|
-
}
|
63
|
-
|
64
|
-
#define GetGyro_Signal(obj, signal) \
|
65
|
-
TypedData_Get_Struct((obj), struct Gyro_Signal, &Gyro_Signal_type, (signal))
|
66
|
-
|
67
|
-
static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
68
|
-
struct Gyro_Signal *signal;
|
69
|
-
VALUE signum = sig;
|
70
|
-
|
71
|
-
GetGyro_Signal(self, signal);
|
72
|
-
GYRO_WATCHER_INITIALIZE(signal, self);
|
73
|
-
signal->signum = NUM2INT(signum);
|
74
|
-
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
75
|
-
|
76
|
-
return Qnil;
|
77
|
-
}
|
78
|
-
|
79
|
-
static VALUE Gyro_Signal_await(VALUE self) {
|
80
|
-
struct Gyro_Signal *signal;
|
81
|
-
VALUE ret;
|
82
|
-
GetGyro_Signal(self, signal);
|
83
|
-
|
84
|
-
signal_activate(signal);
|
85
|
-
ret = Gyro_switchpoint();
|
86
|
-
signal_deactivate(signal);
|
87
|
-
|
88
|
-
TEST_RESUME_EXCEPTION(ret);
|
89
|
-
RB_GC_GUARD(ret);
|
90
|
-
return ret;
|
91
|
-
}
|
92
|
-
|
93
|
-
void Init_Gyro_Signal() {
|
94
|
-
cGyro_Signal = rb_define_class_under(mGyro, "Signal", rb_cData);
|
95
|
-
rb_define_alloc_func(cGyro_Signal, Gyro_Signal_allocate);
|
96
|
-
|
97
|
-
rb_define_method(cGyro_Signal, "initialize", Gyro_Signal_initialize, 1);
|
98
|
-
rb_define_method(cGyro_Signal, "await", Gyro_Signal_await, 0);
|
99
|
-
}
|