polyphony 0.21 → 0.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +5 -5
- data/TODO.md +83 -20
- data/docs/technical-overview/design-principles.md +3 -3
- data/docs/technical-overview/faq.md +11 -0
- data/docs/technical-overview/fiber-scheduling.md +46 -33
- data/examples/core/sleep_spin.rb +2 -2
- data/examples/http/http2_raw.rb +135 -0
- data/examples/http/http_client.rb +14 -3
- data/examples/http/http_get.rb +28 -2
- data/examples/http/http_server.rb +3 -1
- data/examples/http/http_server_forked.rb +3 -1
- data/examples/interfaces/pg_pool.rb +1 -0
- data/examples/io/echo_server.rb +1 -0
- data/ext/gyro/async.c +7 -9
- data/ext/gyro/child.c +5 -8
- data/ext/gyro/extconf.rb +2 -0
- data/ext/gyro/gyro.c +159 -204
- data/ext/gyro/gyro.h +16 -6
- data/ext/gyro/io.c +7 -10
- data/ext/gyro/signal.c +3 -0
- data/ext/gyro/timer.c +9 -18
- data/lib/polyphony/auto_run.rb +12 -5
- data/lib/polyphony/core/coprocess.rb +1 -1
- data/lib/polyphony/core/resource_pool.rb +49 -15
- data/lib/polyphony/core/supervisor.rb +3 -2
- data/lib/polyphony/extensions/core.rb +16 -3
- data/lib/polyphony/extensions/io.rb +2 -0
- data/lib/polyphony/extensions/openssl.rb +60 -0
- data/lib/polyphony/extensions/socket.rb +0 -4
- data/lib/polyphony/http/client/agent.rb +127 -0
- data/lib/polyphony/http/client/http1.rb +129 -0
- data/lib/polyphony/http/client/http2.rb +180 -0
- data/lib/polyphony/http/client/response.rb +32 -0
- data/lib/polyphony/http/client/site_connection_manager.rb +109 -0
- data/lib/polyphony/http/server/request.rb +0 -1
- data/lib/polyphony/http.rb +1 -1
- data/lib/polyphony/net.rb +2 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -4
- data/polyphony.gemspec +1 -0
- data/test/test_gyro.rb +42 -10
- data/test/test_resource_pool.rb +107 -0
- metadata +10 -4
- data/lib/polyphony/http/agent.rb +0 -250
data/ext/gyro/child.c
CHANGED
@@ -82,19 +82,16 @@ static VALUE Gyro_Child_initialize(VALUE self, VALUE pid) {
|
|
82
82
|
}
|
83
83
|
|
84
84
|
void Gyro_Child_callback(struct ev_loop *ev_loop, struct ev_child *ev_child, int revents) {
|
85
|
-
VALUE fiber;
|
86
|
-
VALUE resume_value;
|
87
85
|
struct Gyro_Child *child = (struct Gyro_Child*)ev_child;
|
88
|
-
resume_value = INT2NUM(child->pid);
|
89
86
|
|
90
87
|
child->active = 0;
|
91
88
|
ev_child_stop(EV_DEFAULT, ev_child);
|
92
|
-
Gyro_del_watcher_ref(child->self);
|
93
89
|
|
94
90
|
if (child->fiber != Qnil) {
|
95
|
-
fiber = child->fiber;
|
91
|
+
VALUE fiber = child->fiber;
|
92
|
+
VALUE resume_value = INT2NUM(child->pid);
|
96
93
|
child->fiber = Qnil;
|
97
|
-
|
94
|
+
Gyro_schedule_fiber(fiber, resume_value);
|
98
95
|
}
|
99
96
|
}
|
100
97
|
|
@@ -107,12 +104,12 @@ static VALUE Gyro_Child_await(VALUE self) {
|
|
107
104
|
child->fiber = rb_fiber_current();
|
108
105
|
child->active = 1;
|
109
106
|
ev_child_start(EV_DEFAULT, &child->ev_child);
|
110
|
-
Gyro_add_watcher_ref(self);
|
111
107
|
|
112
|
-
ret =
|
108
|
+
ret = Gyro_yield();
|
113
109
|
|
114
110
|
// fiber is resumed, check if resumed value is an exception
|
115
111
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
112
|
+
printf("* child error\n");
|
116
113
|
if (child->active) {
|
117
114
|
child->active = 0;
|
118
115
|
ev_child_stop(EV_DEFAULT, &child->ev_child);
|
data/ext/gyro/extconf.rb
CHANGED
data/ext/gyro/gyro.c
CHANGED
@@ -1,48 +1,40 @@
|
|
1
1
|
#include "gyro.h"
|
2
2
|
|
3
|
-
static VALUE
|
4
|
-
static VALUE
|
5
|
-
static VALUE Gyro_start(VALUE self);
|
6
|
-
static VALUE Gyro_restart(VALUE self);
|
3
|
+
static VALUE Gyro_break_set(VALUE self);
|
4
|
+
static VALUE Gyro_break_get(VALUE self);
|
7
5
|
|
8
6
|
static VALUE Gyro_ref(VALUE self);
|
9
7
|
static VALUE Gyro_unref(VALUE self);
|
10
8
|
|
11
|
-
static VALUE
|
9
|
+
static VALUE Gyro_reset(VALUE self);
|
12
10
|
static VALUE Gyro_post_fork(VALUE self);
|
13
|
-
|
14
11
|
static VALUE Gyro_suspend(VALUE self);
|
15
12
|
|
16
13
|
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self);
|
17
14
|
static VALUE Fiber_schedule(int argc, VALUE *argv, VALUE self);
|
15
|
+
static VALUE Fiber_state(VALUE self);
|
16
|
+
static VALUE Fiber_mark_as_done(VALUE self);
|
18
17
|
|
19
|
-
void
|
18
|
+
static void Gyro_clear_scheduled_fibers();
|
20
19
|
|
21
20
|
VALUE mGyro;
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
VALUE Gyro_post_run_fiber;
|
26
|
-
|
27
|
-
static VALUE watcher_refs;
|
28
|
-
static VALUE deferred_head;
|
29
|
-
static VALUE deferred_tail;
|
30
|
-
static VALUE deferred_eol_marker;
|
22
|
+
int break_flag = 0;
|
23
|
+
int ref_count = 0;
|
31
24
|
|
32
|
-
static
|
33
|
-
static
|
34
|
-
static int deferred_in_callback;
|
35
|
-
static int break_flag;
|
25
|
+
static VALUE scheduled_head;
|
26
|
+
static VALUE scheduled_tail;
|
36
27
|
|
37
28
|
ID ID_call;
|
38
29
|
ID ID_caller;
|
39
30
|
ID ID_clear;
|
40
|
-
ID
|
41
|
-
ID ID_deferred_prev;
|
31
|
+
ID ID_done;
|
42
32
|
ID ID_each;
|
43
33
|
ID ID_inspect;
|
44
34
|
ID ID_raise;
|
45
35
|
ID ID_read_watcher;
|
36
|
+
ID ID_scheduled;
|
37
|
+
ID ID_scheduled_next;
|
46
38
|
ID ID_scheduled_value;
|
47
39
|
ID ID_transfer;
|
48
40
|
ID ID_write_watcher;
|
@@ -50,267 +42,230 @@ ID ID_R;
|
|
50
42
|
ID ID_W;
|
51
43
|
ID ID_RW;
|
52
44
|
|
45
|
+
VALUE SYM_DEAD;
|
46
|
+
VALUE SYM_RUNNING;
|
47
|
+
VALUE SYM_PAUSED;
|
48
|
+
VALUE SYM_SCHEDULED;
|
49
|
+
|
53
50
|
void Init_Gyro() {
|
54
51
|
mGyro = rb_define_module("Gyro");
|
55
52
|
|
56
|
-
rb_define_singleton_method(mGyro, "break", Gyro_break, 0);
|
57
|
-
rb_define_singleton_method(mGyro, "defer", Gyro_defer, 0);
|
58
|
-
rb_define_singleton_method(mGyro, "post_fork", Gyro_post_fork, 0);
|
59
53
|
rb_define_singleton_method(mGyro, "ref", Gyro_ref, 0);
|
60
|
-
rb_define_singleton_method(mGyro, "start", Gyro_start, 0);
|
61
|
-
rb_define_singleton_method(mGyro, "restart", Gyro_restart, 0);
|
62
|
-
rb_define_singleton_method(mGyro, "snooze", Gyro_snooze, 0);
|
63
54
|
rb_define_singleton_method(mGyro, "unref", Gyro_unref, 0);
|
64
55
|
|
65
|
-
|
56
|
+
rb_define_singleton_method(mGyro, "reset!", Gyro_reset, 0);
|
57
|
+
rb_define_singleton_method(mGyro, "post_fork", Gyro_post_fork, 0);
|
58
|
+
rb_define_singleton_method(mGyro, "snooze", Gyro_snooze, 0);
|
59
|
+
|
60
|
+
rb_define_singleton_method(mGyro, "break!", Gyro_break_set, 0);
|
61
|
+
rb_define_singleton_method(mGyro, "break?", Gyro_break_get, 0);
|
62
|
+
|
66
63
|
rb_define_global_function("snooze", Gyro_snooze, 0);
|
67
64
|
rb_define_global_function("suspend", Gyro_suspend, 0);
|
68
65
|
|
69
66
|
VALUE cFiber = rb_const_get(rb_cObject, rb_intern("Fiber"));
|
70
67
|
rb_define_method(cFiber, "safe_transfer", Fiber_safe_transfer, -1);
|
71
68
|
rb_define_method(cFiber, "schedule", Fiber_schedule, -1);
|
69
|
+
rb_define_method(cFiber, "state", Fiber_state, 0);
|
70
|
+
rb_define_method(cFiber, "mark_as_done!", Fiber_mark_as_done, 0);
|
72
71
|
|
73
72
|
ID_call = rb_intern("call");
|
74
73
|
ID_caller = rb_intern("caller");
|
75
74
|
ID_clear = rb_intern("clear");
|
76
|
-
|
77
|
-
ID_deferred_prev = rb_intern("deferred_prev");
|
75
|
+
ID_done = rb_intern("done");
|
78
76
|
ID_each = rb_intern("each");
|
79
77
|
ID_inspect = rb_intern("inspect");
|
80
78
|
ID_raise = rb_intern("raise");
|
81
79
|
ID_read_watcher = rb_intern("read_watcher");
|
82
|
-
|
80
|
+
ID_scheduled = rb_intern("scheduled");
|
81
|
+
ID_scheduled_next = rb_intern("scheduled_next");
|
82
|
+
ID_scheduled_value = rb_intern("scheduled_value");
|
83
83
|
ID_transfer = rb_intern("transfer");
|
84
84
|
ID_write_watcher = rb_intern("write_watcher");
|
85
85
|
ID_R = rb_intern("r");
|
86
86
|
ID_W = rb_intern("w");
|
87
87
|
ID_RW = rb_intern("rw");
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
rb_global_variable(&
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
89
|
+
SYM_DEAD = ID2SYM(rb_intern("dead"));
|
90
|
+
SYM_RUNNING = ID2SYM(rb_intern("running"));
|
91
|
+
SYM_PAUSED = ID2SYM(rb_intern("paused"));
|
92
|
+
SYM_SCHEDULED = ID2SYM(rb_intern("scheduled"));
|
93
|
+
rb_global_variable(&SYM_DEAD);
|
94
|
+
rb_global_variable(&SYM_RUNNING);
|
95
|
+
rb_global_variable(&SYM_PAUSED);
|
96
|
+
rb_global_variable(&SYM_SCHEDULED);
|
97
|
+
|
98
|
+
scheduled_head = Qnil;
|
99
|
+
scheduled_tail = Qnil;
|
100
|
+
rb_global_variable(&scheduled_head);
|
101
|
+
}
|
99
102
|
|
100
|
-
|
101
|
-
|
103
|
+
static VALUE Gyro_ref(VALUE self) {
|
104
|
+
Gyro_ref_count_incr();
|
105
|
+
return Qnil;
|
106
|
+
}
|
102
107
|
|
103
|
-
|
104
|
-
|
105
|
-
|
108
|
+
static VALUE Gyro_unref(VALUE self) {
|
109
|
+
Gyro_ref_count_decr();
|
110
|
+
return Qnil;
|
106
111
|
}
|
107
112
|
|
108
|
-
static VALUE
|
113
|
+
static VALUE Gyro_reset(VALUE self) {
|
109
114
|
break_flag = 0;
|
110
|
-
|
111
|
-
ev_run(EV_DEFAULT, 0);
|
112
|
-
rb_gv_set("__reactor_fiber__", Qnil);
|
113
|
-
|
114
|
-
if (Gyro_post_run_fiber != Qnil) {
|
115
|
-
rb_funcall(Gyro_post_run_fiber, ID_transfer, 0);
|
116
|
-
}
|
115
|
+
ref_count = 0;
|
117
116
|
|
117
|
+
Gyro_clear_scheduled_fibers();
|
118
118
|
return Qnil;
|
119
119
|
}
|
120
120
|
|
121
|
-
static VALUE
|
121
|
+
static VALUE Gyro_break_set(VALUE self) {
|
122
122
|
break_flag = 1;
|
123
|
-
// make sure reactor fiber is alive
|
124
|
-
if (!RTEST(rb_fiber_alive_p(Gyro_reactor_fiber))) {
|
125
|
-
return Qnil;
|
126
|
-
}
|
127
|
-
|
128
|
-
if (deferred_active) {
|
129
|
-
deferred_active = 0;
|
130
|
-
ev_idle_stop(EV_DEFAULT, &idle_watcher);
|
131
|
-
}
|
132
123
|
ev_break(EV_DEFAULT, EVBREAK_ALL);
|
133
|
-
|
124
|
+
// printf("\n");
|
134
125
|
return Qnil;
|
135
126
|
}
|
136
127
|
|
137
|
-
static VALUE
|
138
|
-
|
139
|
-
deferred_head = Qnil;
|
140
|
-
Gyro_reactor_fiber = rb_fiber_new(Gyro_run, Qnil);
|
141
|
-
rb_gv_set("__reactor_fiber__", Gyro_reactor_fiber);
|
142
|
-
return Qnil;
|
128
|
+
static VALUE Gyro_break_get(VALUE self) {
|
129
|
+
return (break_flag == 0) ? Qfalse : Qtrue;
|
143
130
|
}
|
144
131
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
// control will be transferred back to here after reactor loop is done
|
149
|
-
Gyro_start(self);
|
132
|
+
VALUE Gyro_snooze(VALUE self) {
|
133
|
+
VALUE fiber = rb_fiber_current();
|
134
|
+
Gyro_schedule_fiber(fiber, Qnil);
|
150
135
|
|
151
|
-
|
136
|
+
VALUE ret = Gyro_run();
|
137
|
+
if (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
|
138
|
+
return rb_funcall(ret, ID_raise, 1, ret);
|
139
|
+
else
|
140
|
+
return ret;
|
152
141
|
}
|
153
142
|
|
154
|
-
static VALUE
|
155
|
-
|
156
|
-
|
157
|
-
|
143
|
+
static VALUE Gyro_post_fork(VALUE self) {
|
144
|
+
ev_loop_fork(EV_DEFAULT);
|
145
|
+
break_flag = 0;
|
146
|
+
ref_count = 0;
|
147
|
+
|
148
|
+
Gyro_clear_scheduled_fibers();
|
158
149
|
|
159
|
-
static VALUE Gyro_unref(VALUE self) {
|
160
|
-
ev_unref(EV_DEFAULT);
|
161
150
|
return Qnil;
|
162
151
|
}
|
163
152
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
void Gyro_del_watcher_ref(VALUE obj) {
|
169
|
-
rb_hash_delete(watcher_refs, rb_obj_id(obj));
|
170
|
-
}
|
171
|
-
|
172
|
-
static void defer_add(VALUE item) {
|
173
|
-
if (NIL_P(deferred_head)) {
|
174
|
-
deferred_head = item;
|
175
|
-
deferred_tail = item;
|
176
|
-
rb_ivar_set(item, ID_deferred_next, Qnil);
|
177
|
-
rb_ivar_set(item, ID_deferred_prev, Qnil);
|
178
|
-
}
|
179
|
-
else {
|
180
|
-
rb_ivar_set(deferred_tail, ID_deferred_next, item);
|
181
|
-
rb_ivar_set(item, ID_deferred_prev, deferred_tail);
|
182
|
-
deferred_tail = item;
|
183
|
-
}
|
184
|
-
|
185
|
-
if (!deferred_active) {
|
186
|
-
deferred_active = 1;
|
187
|
-
ev_idle_start(EV_DEFAULT, &idle_watcher);
|
153
|
+
static VALUE Gyro_suspend(VALUE self) {
|
154
|
+
VALUE ret = Gyro_run();
|
155
|
+
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
156
|
+
return rb_funcall(ret, ID_raise, 1, ret);
|
188
157
|
}
|
158
|
+
else
|
159
|
+
return ret;
|
189
160
|
}
|
190
161
|
|
191
|
-
static
|
192
|
-
VALUE
|
193
|
-
VALUE
|
194
|
-
if (RTEST(prev)) {
|
195
|
-
rb_ivar_set(prev, ID_deferred_next, next);
|
196
|
-
}
|
197
|
-
if (RTEST(next)) {
|
198
|
-
rb_ivar_set(next, ID_deferred_prev, prev);
|
199
|
-
}
|
162
|
+
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
163
|
+
VALUE arg = (argc == 0) ? Qnil : argv[0];
|
164
|
+
VALUE ret = rb_funcall(self, ID_transfer, 1, arg);
|
200
165
|
|
166
|
+
// fiber is resumed, check if resumed value is an exception
|
167
|
+
return RTEST(rb_obj_is_kind_of(ret, rb_eException)) ?
|
168
|
+
rb_funcall(ret, ID_raise, 1, ret) : ret;
|
201
169
|
}
|
202
170
|
|
203
|
-
static VALUE
|
204
|
-
VALUE
|
205
|
-
|
206
|
-
|
207
|
-
}
|
208
|
-
return Qnil;
|
171
|
+
static VALUE Fiber_schedule(int argc, VALUE *argv, VALUE self) {
|
172
|
+
VALUE value = (argc == 0) ? Qnil : argv[0];
|
173
|
+
Gyro_schedule_fiber(self, value);
|
174
|
+
return self;
|
209
175
|
}
|
210
176
|
|
211
|
-
VALUE
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
ret = YIELD_TO_REACTOR();
|
177
|
+
static VALUE Fiber_state(VALUE self) {
|
178
|
+
if (!rb_fiber_alive_p(self) || (rb_ivar_get(self, ID_done) != Qnil))
|
179
|
+
return SYM_DEAD;
|
180
|
+
if (rb_fiber_current() == self) return SYM_RUNNING;
|
181
|
+
if (rb_ivar_get(self, ID_scheduled) != Qnil) return SYM_SCHEDULED;
|
217
182
|
|
218
|
-
|
219
|
-
defer_remove(fiber);
|
220
|
-
return rb_funcall(ret, ID_raise, 1, ret);
|
221
|
-
}
|
222
|
-
else {
|
223
|
-
return ret;
|
224
|
-
}
|
183
|
+
return SYM_PAUSED;
|
225
184
|
}
|
226
185
|
|
227
|
-
static VALUE
|
228
|
-
|
229
|
-
|
230
|
-
Gyro_reactor_fiber = rb_fiber_new(Gyro_run, Qnil);
|
231
|
-
rb_gv_set("__reactor_fiber__", Gyro_reactor_fiber);
|
232
|
-
Gyro_root_fiber = rb_fiber_current();
|
233
|
-
|
234
|
-
deferred_head = Qnil;
|
235
|
-
deferred_active = 0;
|
236
|
-
|
237
|
-
return Qnil;
|
186
|
+
static VALUE Fiber_mark_as_done(VALUE self) {
|
187
|
+
rb_ivar_set(self, ID_done, Qtrue);
|
188
|
+
return self;
|
238
189
|
}
|
239
190
|
|
240
|
-
VALUE
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
VALUE arg = rb_ivar_get(item, ID_scheduled_value);
|
246
|
-
if (RTEST(rb_obj_is_kind_of(arg, rb_eException))) {
|
247
|
-
rb_ivar_set(item, ID_scheduled_value, Qnil);
|
248
|
-
}
|
249
|
-
SCHEDULE_FIBER(item, 1, arg);
|
250
|
-
}
|
251
|
-
return Qnil;
|
191
|
+
VALUE Gyro_yield() {
|
192
|
+
Gyro_ref_count_incr();
|
193
|
+
VALUE ret = Gyro_run();
|
194
|
+
Gyro_ref_count_decr();
|
195
|
+
return ret;
|
252
196
|
}
|
253
197
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
VALUE next = rb_ivar_get(deferred_head, ID_deferred_next);
|
261
|
-
if (deferred_head == deferred_eol_marker) {
|
262
|
-
deferred_head = next;
|
198
|
+
VALUE Gyro_run() {
|
199
|
+
while (1) {
|
200
|
+
if (break_flag != 0) {
|
201
|
+
return Qnil;
|
202
|
+
}
|
203
|
+
if ((scheduled_head != Qnil) || (ref_count == 0)) {
|
263
204
|
break;
|
264
205
|
}
|
265
|
-
|
266
|
-
deferred_head = next;
|
206
|
+
ev_run(EV_DEFAULT, EVRUN_ONCE);
|
267
207
|
}
|
268
208
|
|
269
|
-
if
|
270
|
-
|
271
|
-
|
209
|
+
// return if no fiber is scheduled
|
210
|
+
if (scheduled_head == Qnil) {
|
211
|
+
return Qnil;
|
272
212
|
}
|
273
213
|
|
274
|
-
|
275
|
-
|
214
|
+
// update scheduled linked list refs
|
215
|
+
VALUE next_fiber = scheduled_head;
|
216
|
+
VALUE next_next_fiber = rb_ivar_get(next_fiber, ID_scheduled_next);
|
217
|
+
rb_ivar_set(next_fiber, ID_scheduled_next, Qnil);
|
218
|
+
scheduled_head = next_next_fiber;
|
219
|
+
if (scheduled_head == Qnil) {
|
220
|
+
scheduled_tail = Qnil;
|
221
|
+
}
|
276
222
|
|
277
|
-
|
278
|
-
if (!RTEST(rb_fiber_alive_p(Gyro_reactor_fiber))) {
|
223
|
+
if (rb_fiber_alive_p(next_fiber) != Qtrue)
|
279
224
|
return Qnil;
|
280
|
-
}
|
281
225
|
|
282
|
-
|
226
|
+
// run next fiber
|
227
|
+
VALUE value = rb_ivar_get(next_fiber, ID_scheduled_value);
|
228
|
+
rb_ivar_set(next_fiber, ID_scheduled_value, Qnil);
|
229
|
+
rb_ivar_set(next_fiber, ID_scheduled, Qnil);
|
230
|
+
return rb_funcall(next_fiber, ID_transfer, 1, value);
|
231
|
+
}
|
283
232
|
|
284
|
-
|
285
|
-
|
286
|
-
|
233
|
+
void Gyro_schedule_fiber(VALUE fiber, VALUE value) {
|
234
|
+
rb_ivar_set(fiber, ID_scheduled_value, value);
|
235
|
+
// if fiber is already scheduled, we just set the scheduled value, then return
|
236
|
+
if (rb_ivar_get(fiber, ID_scheduled) != Qnil)
|
237
|
+
return;
|
238
|
+
|
239
|
+
rb_ivar_set(fiber, ID_scheduled, Qtrue);
|
240
|
+
|
241
|
+
// put fiber on scheduled list
|
242
|
+
if (scheduled_head != Qnil) {
|
243
|
+
VALUE last = scheduled_tail;
|
244
|
+
rb_ivar_set(last, ID_scheduled_next, fiber);
|
245
|
+
scheduled_tail = fiber;
|
246
|
+
}
|
247
|
+
else {
|
248
|
+
scheduled_tail = scheduled_head = fiber;
|
249
|
+
}
|
287
250
|
}
|
288
251
|
|
289
|
-
|
290
|
-
|
291
|
-
|
252
|
+
int Gyro_ref_count() {
|
253
|
+
return ref_count;
|
254
|
+
}
|
292
255
|
|
293
|
-
|
294
|
-
|
295
|
-
rb_funcall(ret, ID_raise, 1, ret) : ret;
|
256
|
+
void Gyro_ref_count_incr() {
|
257
|
+
ref_count += 1;
|
296
258
|
}
|
297
259
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
VALUE next = deferred_head;
|
308
|
-
while (RTEST(next)) {
|
309
|
-
if (next == self) return self;
|
310
|
-
if (next == deferred_eol_marker) break;
|
311
|
-
next = rb_ivar_get(next, ID_deferred_next);
|
312
|
-
}
|
260
|
+
void Gyro_ref_count_decr() {
|
261
|
+
ref_count -= 1;
|
262
|
+
}
|
263
|
+
|
264
|
+
static void Gyro_clear_scheduled_fibers() {
|
265
|
+
while (scheduled_head != Qnil) {
|
266
|
+
VALUE fiber = scheduled_head;
|
267
|
+
scheduled_head = rb_ivar_get(fiber, ID_scheduled_next);
|
268
|
+
rb_ivar_set(fiber, ID_scheduled_next, Qnil);
|
313
269
|
}
|
314
|
-
|
315
|
-
return self;
|
270
|
+
scheduled_tail = Qnil;
|
316
271
|
}
|
data/ext/gyro/gyro.h
CHANGED
@@ -5,10 +5,24 @@
|
|
5
5
|
#include "ruby/io.h"
|
6
6
|
#include "libev.h"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
enum {
|
9
|
+
FIBER_STATE_NOT_SCHEDULED = 0,
|
10
|
+
FIBER_STATE_WAITING = 1,
|
11
|
+
FIBER_STATE_SCHEDULED = 2
|
12
|
+
};
|
13
|
+
|
14
|
+
// void Gyro_add_watcher_ref(VALUE obj);
|
15
|
+
// void Gyro_del_watcher_ref(VALUE obj);
|
10
16
|
VALUE Gyro_snooze(VALUE self);
|
11
17
|
|
18
|
+
VALUE Gyro_run();
|
19
|
+
VALUE Gyro_yield();
|
20
|
+
void Gyro_schedule_fiber(VALUE fiber, VALUE value);
|
21
|
+
|
22
|
+
int Gyro_ref_count();
|
23
|
+
void Gyro_ref_count_incr();
|
24
|
+
void Gyro_ref_count_decr();
|
25
|
+
|
12
26
|
VALUE IO_read_watcher(VALUE io);
|
13
27
|
VALUE IO_write_watcher(VALUE io);
|
14
28
|
VALUE Gyro_IO_await(VALUE self);
|
@@ -17,9 +31,6 @@ int io_setstrbuf(VALUE *str, long len);
|
|
17
31
|
void io_set_read_length(VALUE str, long n, int shrinkable);
|
18
32
|
VALUE io_enc_str(VALUE str, rb_io_t *fptr);
|
19
33
|
|
20
|
-
#define SCHEDULE_FIBER(obj, args...) rb_funcall(obj, ID_transfer, args)
|
21
|
-
#define YIELD_TO_REACTOR() rb_funcall(Gyro_reactor_fiber, ID_transfer, 0)
|
22
|
-
|
23
34
|
#define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
|
24
35
|
|
25
36
|
extern VALUE mGyro;
|
@@ -32,7 +43,6 @@ extern ID ID_caller;
|
|
32
43
|
extern ID ID_clear;
|
33
44
|
extern ID ID_each;
|
34
45
|
extern ID ID_inspect;
|
35
|
-
extern ID ID_next_deferred;
|
36
46
|
extern ID ID_raise;
|
37
47
|
extern ID ID_read_watcher;
|
38
48
|
extern ID ID_scheduled_value;
|
data/ext/gyro/io.c
CHANGED
@@ -102,18 +102,15 @@ static VALUE Gyro_IO_initialize(VALUE self, VALUE io_obj, VALUE event_mask) {
|
|
102
102
|
}
|
103
103
|
|
104
104
|
void Gyro_IO_callback(struct ev_loop *ev_loop, struct ev_io *ev_io, int revents) {
|
105
|
-
VALUE fiber;
|
106
105
|
struct Gyro_IO *io = (struct Gyro_IO*)ev_io;
|
107
106
|
|
107
|
+
ev_io_stop(EV_DEFAULT, ev_io);
|
108
|
+
io->active = 0;
|
109
|
+
|
108
110
|
if (io->fiber != Qnil) {
|
109
|
-
|
110
|
-
io->active = 0;
|
111
|
-
fiber = io->fiber;
|
111
|
+
VALUE fiber = io->fiber;
|
112
112
|
io->fiber = Qnil;
|
113
|
-
|
114
|
-
}
|
115
|
-
else {
|
116
|
-
ev_io_stop(EV_DEFAULT, ev_io);
|
113
|
+
Gyro_schedule_fiber(fiber, Qnil);
|
117
114
|
}
|
118
115
|
}
|
119
116
|
|
@@ -126,9 +123,10 @@ VALUE Gyro_IO_await(VALUE self) {
|
|
126
123
|
io->fiber = rb_fiber_current();
|
127
124
|
io->active = 1;
|
128
125
|
ev_io_start(EV_DEFAULT, &io->ev_io);
|
129
|
-
ret =
|
126
|
+
ret = Gyro_yield();
|
130
127
|
|
131
128
|
// make sure io watcher is stopped
|
129
|
+
io->fiber = Qnil;
|
132
130
|
if (io->active) {
|
133
131
|
io->active = 0;
|
134
132
|
ev_io_stop(EV_DEFAULT, &io->ev_io);
|
@@ -376,7 +374,6 @@ static VALUE IO_write(int argc, VALUE *argv, VALUE io) {
|
|
376
374
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
377
375
|
if (write_watcher == Qnil)
|
378
376
|
write_watcher = IO_write_watcher(io);
|
379
|
-
// write_watcher = rb_funcall(io, ID_write_watcher, 0);
|
380
377
|
Gyro_IO_await(write_watcher);
|
381
378
|
}
|
382
379
|
else {
|
data/ext/gyro/signal.c
CHANGED
@@ -79,6 +79,7 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
79
79
|
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
80
80
|
|
81
81
|
signal->active = 1;
|
82
|
+
Gyro_ref_count_incr();
|
82
83
|
ev_signal_start(EV_DEFAULT, &signal->ev_signal);
|
83
84
|
|
84
85
|
return Qnil;
|
@@ -97,6 +98,7 @@ static VALUE Gyro_Signal_start(VALUE self) {
|
|
97
98
|
GetGyro_Signal(self, signal);
|
98
99
|
|
99
100
|
if (!signal->active) {
|
101
|
+
Gyro_ref_count_incr();
|
100
102
|
ev_signal_start(EV_DEFAULT, &signal->ev_signal);
|
101
103
|
signal->active = 1;
|
102
104
|
}
|
@@ -109,6 +111,7 @@ static VALUE Gyro_Signal_stop(VALUE self) {
|
|
109
111
|
GetGyro_Signal(self, signal);
|
110
112
|
|
111
113
|
if (signal->active) {
|
114
|
+
Gyro_ref_count_decr();
|
112
115
|
ev_signal_stop(EV_DEFAULT, &signal->ev_signal);
|
113
116
|
signal->active = 0;
|
114
117
|
}
|