polyphony 0.21 → 0.22
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.
- 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
|
}
|