polyphony 0.22 → 0.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/Gemfile.lock +9 -1
- data/TODO.md +13 -38
- data/docs/summary.md +19 -5
- data/docs/technical-overview/faq.md +12 -0
- data/examples/core/01-spinning-up-coprocesses.rb +2 -6
- data/examples/core/02-awaiting-coprocesses.rb +3 -1
- data/examples/core/03-interrupting.rb +3 -1
- data/examples/core/04-no-auto-run.rb +1 -3
- data/examples/core/cancel.rb +1 -1
- data/examples/core/channel_echo.rb +3 -1
- data/examples/core/defer.rb +3 -1
- data/examples/core/enumerator.rb +3 -1
- data/examples/core/error_bubbling.rb +35 -0
- data/examples/core/fork.rb +1 -1
- data/examples/core/genserver.rb +1 -1
- data/examples/core/lock.rb +3 -1
- data/examples/core/move_on.rb +1 -1
- data/examples/core/move_on_twice.rb +1 -1
- data/examples/core/move_on_with_ensure.rb +1 -1
- data/examples/core/move_on_with_value.rb +1 -1
- data/examples/core/multiple_spin.rb +3 -1
- data/examples/core/nested_cancel.rb +1 -1
- data/examples/core/nested_multiple_spin.rb +3 -1
- data/examples/core/nested_spin.rb +3 -1
- data/examples/core/pulse.rb +1 -1
- data/examples/core/resource.rb +1 -1
- data/examples/core/resource_cancel.rb +2 -2
- data/examples/core/resource_delegate.rb +1 -1
- data/examples/core/sleep.rb +1 -1
- data/examples/core/sleep_spin.rb +3 -1
- data/examples/core/snooze.rb +1 -1
- data/examples/core/spin_error.rb +2 -1
- data/examples/core/spin_error_backtrace.rb +1 -1
- data/examples/core/spin_uncaught_error.rb +3 -1
- data/examples/core/supervisor.rb +1 -1
- data/examples/core/supervisor_with_cancel_scope.rb +1 -1
- data/examples/core/supervisor_with_error.rb +3 -1
- data/examples/core/supervisor_with_manual_move_on.rb +1 -1
- data/examples/core/suspend.rb +1 -1
- data/examples/core/thread.rb +3 -3
- data/examples/core/thread_cancel.rb +6 -3
- data/examples/core/thread_pool.rb +8 -52
- data/examples/core/thread_pool_perf.rb +63 -0
- data/examples/core/throttle.rb +3 -1
- data/examples/core/timeout.rb +1 -1
- data/examples/core/wait_for_signal.rb +4 -2
- data/examples/fs/read.rb +1 -1
- data/examples/http/http2_raw.rb +1 -1
- data/examples/http/http_get.rb +1 -1
- data/examples/http/http_server.rb +2 -1
- data/examples/http/http_server_graceful.rb +3 -1
- data/examples/http/http_ws_server.rb +0 -2
- data/examples/http/https_wss_server.rb +0 -2
- data/examples/http/websocket_secure_server.rb +0 -2
- data/examples/http/websocket_server.rb +0 -2
- data/examples/interfaces/redis_channels.rb +3 -1
- data/examples/interfaces/redis_pubsub.rb +3 -1
- data/examples/interfaces/redis_pubsub_perf.rb +3 -1
- data/examples/io/backticks.rb +1 -1
- data/examples/io/cat.rb +1 -1
- data/examples/io/echo_client.rb +1 -1
- data/examples/io/echo_client_from_stdin.rb +3 -1
- data/examples/io/echo_pipe.rb +1 -1
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_with_timeout.rb +1 -1
- data/examples/io/echo_stdin.rb +1 -1
- data/examples/io/httparty_multi.rb +1 -1
- data/examples/io/io_read.rb +1 -1
- data/examples/io/irb.rb +1 -1
- data/examples/io/net-http.rb +1 -1
- data/examples/io/open.rb +1 -1
- data/examples/io/system.rb +1 -1
- data/examples/io/tcpserver.rb +1 -1
- data/examples/io/tcpsocket.rb +1 -1
- data/examples/performance/multi_snooze.rb +1 -1
- data/examples/performance/snooze.rb +18 -10
- data/ext/gyro/async.c +16 -9
- data/ext/gyro/child.c +2 -2
- data/ext/gyro/gyro.c +17 -10
- data/ext/gyro/gyro.h +2 -2
- data/ext/gyro/io.c +2 -2
- data/ext/gyro/signal.c +33 -35
- data/ext/gyro/timer.c +6 -73
- data/lib/polyphony.rb +6 -8
- data/lib/polyphony/core/cancel_scope.rb +32 -21
- data/lib/polyphony/core/coprocess.rb +26 -23
- data/lib/polyphony/core/global_api.rb +86 -0
- data/lib/polyphony/core/resource_pool.rb +1 -1
- data/lib/polyphony/core/supervisor.rb +47 -13
- data/lib/polyphony/core/thread.rb +10 -36
- data/lib/polyphony/core/thread_pool.rb +6 -26
- data/lib/polyphony/extensions/core.rb +30 -100
- data/lib/polyphony/extensions/io.rb +10 -7
- data/lib/polyphony/extensions/openssl.rb +18 -28
- data/lib/polyphony/http/client/agent.rb +15 -11
- data/lib/polyphony/http/client/http2.rb +1 -1
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -0
- data/test/coverage.rb +45 -0
- data/test/helper.rb +15 -5
- data/test/test_async.rb +4 -4
- data/test/test_cancel_scope.rb +109 -0
- data/test/test_coprocess.rb +80 -36
- data/test/{test_core.rb → test_global_api.rb} +67 -13
- data/test/test_gyro.rb +1 -5
- data/test/test_io.rb +2 -2
- data/test/test_resource_pool.rb +19 -0
- data/test/test_signal.rb +10 -5
- data/test/test_supervisor.rb +168 -0
- data/test/test_timer.rb +31 -5
- metadata +23 -4
- data/lib/polyphony/auto_run.rb +0 -19
data/ext/gyro/child.c
CHANGED
@@ -105,7 +105,7 @@ static VALUE Gyro_Child_await(VALUE self) {
|
|
105
105
|
child->active = 1;
|
106
106
|
ev_child_start(EV_DEFAULT, &child->ev_child);
|
107
107
|
|
108
|
-
ret =
|
108
|
+
ret = Gyro_await();
|
109
109
|
|
110
110
|
// fiber is resumed, check if resumed value is an exception
|
111
111
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
@@ -114,7 +114,7 @@ static VALUE Gyro_Child_await(VALUE self) {
|
|
114
114
|
child->active = 0;
|
115
115
|
ev_child_stop(EV_DEFAULT, &child->ev_child);
|
116
116
|
}
|
117
|
-
return rb_funcall(
|
117
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
118
118
|
}
|
119
119
|
else {
|
120
120
|
return ret;
|
data/ext/gyro/gyro.c
CHANGED
@@ -6,6 +6,7 @@ static VALUE Gyro_break_get(VALUE self);
|
|
6
6
|
static VALUE Gyro_ref(VALUE self);
|
7
7
|
static VALUE Gyro_unref(VALUE self);
|
8
8
|
|
9
|
+
static VALUE Gyro_run(VALUE self);
|
9
10
|
static VALUE Gyro_reset(VALUE self);
|
10
11
|
static VALUE Gyro_post_fork(VALUE self);
|
11
12
|
static VALUE Gyro_suspend(VALUE self);
|
@@ -53,6 +54,7 @@ void Init_Gyro() {
|
|
53
54
|
rb_define_singleton_method(mGyro, "ref", Gyro_ref, 0);
|
54
55
|
rb_define_singleton_method(mGyro, "unref", Gyro_unref, 0);
|
55
56
|
|
57
|
+
rb_define_singleton_method(mGyro, "run", Gyro_run, 0);
|
56
58
|
rb_define_singleton_method(mGyro, "reset!", Gyro_reset, 0);
|
57
59
|
rb_define_singleton_method(mGyro, "post_fork", Gyro_post_fork, 0);
|
58
60
|
rb_define_singleton_method(mGyro, "snooze", Gyro_snooze, 0);
|
@@ -110,6 +112,10 @@ static VALUE Gyro_unref(VALUE self) {
|
|
110
112
|
return Qnil;
|
111
113
|
}
|
112
114
|
|
115
|
+
static VALUE Gyro_run(VALUE self) {
|
116
|
+
return Gyro_run_next_fiber();
|
117
|
+
}
|
118
|
+
|
113
119
|
static VALUE Gyro_reset(VALUE self) {
|
114
120
|
break_flag = 0;
|
115
121
|
ref_count = 0;
|
@@ -121,7 +127,6 @@ static VALUE Gyro_reset(VALUE self) {
|
|
121
127
|
static VALUE Gyro_break_set(VALUE self) {
|
122
128
|
break_flag = 1;
|
123
129
|
ev_break(EV_DEFAULT, EVBREAK_ALL);
|
124
|
-
// printf("\n");
|
125
130
|
return Qnil;
|
126
131
|
}
|
127
132
|
|
@@ -133,9 +138,9 @@ VALUE Gyro_snooze(VALUE self) {
|
|
133
138
|
VALUE fiber = rb_fiber_current();
|
134
139
|
Gyro_schedule_fiber(fiber, Qnil);
|
135
140
|
|
136
|
-
VALUE ret =
|
141
|
+
VALUE ret = Gyro_run_next_fiber();
|
137
142
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException)))
|
138
|
-
return rb_funcall(
|
143
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
139
144
|
else
|
140
145
|
return ret;
|
141
146
|
}
|
@@ -151,9 +156,10 @@ static VALUE Gyro_post_fork(VALUE self) {
|
|
151
156
|
}
|
152
157
|
|
153
158
|
static VALUE Gyro_suspend(VALUE self) {
|
154
|
-
|
159
|
+
rb_ivar_set(self, ID_scheduled_value, Qnil);
|
160
|
+
VALUE ret = Gyro_run_next_fiber();
|
155
161
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
156
|
-
return rb_funcall(
|
162
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
157
163
|
}
|
158
164
|
else
|
159
165
|
return ret;
|
@@ -165,7 +171,7 @@ static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
|
165
171
|
|
166
172
|
// fiber is resumed, check if resumed value is an exception
|
167
173
|
return RTEST(rb_obj_is_kind_of(ret, rb_eException)) ?
|
168
|
-
rb_funcall(
|
174
|
+
rb_funcall(rb_mKernel, ID_raise, 1, ret) : ret;
|
169
175
|
}
|
170
176
|
|
171
177
|
static VALUE Fiber_schedule(int argc, VALUE *argv, VALUE self) {
|
@@ -188,14 +194,14 @@ static VALUE Fiber_mark_as_done(VALUE self) {
|
|
188
194
|
return self;
|
189
195
|
}
|
190
196
|
|
191
|
-
VALUE
|
197
|
+
VALUE Gyro_await() {
|
192
198
|
Gyro_ref_count_incr();
|
193
|
-
VALUE ret =
|
199
|
+
VALUE ret = Gyro_run_next_fiber();
|
194
200
|
Gyro_ref_count_decr();
|
195
201
|
return ret;
|
196
202
|
}
|
197
203
|
|
198
|
-
VALUE
|
204
|
+
VALUE Gyro_run_next_fiber() {
|
199
205
|
while (1) {
|
200
206
|
if (break_flag != 0) {
|
201
207
|
return Qnil;
|
@@ -220,8 +226,9 @@ VALUE Gyro_run() {
|
|
220
226
|
scheduled_tail = Qnil;
|
221
227
|
}
|
222
228
|
|
223
|
-
if (rb_fiber_alive_p(next_fiber) != Qtrue)
|
229
|
+
if (rb_fiber_alive_p(next_fiber) != Qtrue) {
|
224
230
|
return Qnil;
|
231
|
+
}
|
225
232
|
|
226
233
|
// run next fiber
|
227
234
|
VALUE value = rb_ivar_get(next_fiber, ID_scheduled_value);
|
data/ext/gyro/gyro.h
CHANGED
@@ -15,8 +15,8 @@ enum {
|
|
15
15
|
// void Gyro_del_watcher_ref(VALUE obj);
|
16
16
|
VALUE Gyro_snooze(VALUE self);
|
17
17
|
|
18
|
-
VALUE
|
19
|
-
VALUE
|
18
|
+
VALUE Gyro_run_next_fiber();
|
19
|
+
VALUE Gyro_await();
|
20
20
|
void Gyro_schedule_fiber(VALUE fiber, VALUE value);
|
21
21
|
|
22
22
|
int Gyro_ref_count();
|
data/ext/gyro/io.c
CHANGED
@@ -123,7 +123,7 @@ VALUE Gyro_IO_await(VALUE self) {
|
|
123
123
|
io->fiber = rb_fiber_current();
|
124
124
|
io->active = 1;
|
125
125
|
ev_io_start(EV_DEFAULT, &io->ev_io);
|
126
|
-
ret =
|
126
|
+
ret = Gyro_await();
|
127
127
|
|
128
128
|
// make sure io watcher is stopped
|
129
129
|
io->fiber = Qnil;
|
@@ -134,7 +134,7 @@ VALUE Gyro_IO_await(VALUE self) {
|
|
134
134
|
|
135
135
|
// fiber is resumed, check if resumed value is an exception
|
136
136
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
137
|
-
return rb_funcall(
|
137
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
138
138
|
}
|
139
139
|
else {
|
140
140
|
return Qnil;
|
data/ext/gyro/signal.c
CHANGED
@@ -4,7 +4,7 @@ struct Gyro_Signal {
|
|
4
4
|
struct ev_signal ev_signal;
|
5
5
|
int active;
|
6
6
|
int signum;
|
7
|
-
VALUE
|
7
|
+
VALUE fiber;
|
8
8
|
};
|
9
9
|
|
10
10
|
static VALUE cGyro_Signal = Qnil;
|
@@ -18,8 +18,7 @@ static size_t Gyro_Signal_size(const void *ptr);
|
|
18
18
|
/* Methods */
|
19
19
|
static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig);
|
20
20
|
|
21
|
-
static VALUE
|
22
|
-
static VALUE Gyro_Signal_stop(VALUE self);
|
21
|
+
static VALUE Gyro_Signal_await(VALUE self);
|
23
22
|
|
24
23
|
void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *signal, int revents);
|
25
24
|
|
@@ -29,8 +28,7 @@ void Init_Gyro_Signal() {
|
|
29
28
|
rb_define_alloc_func(cGyro_Signal, Gyro_Signal_allocate);
|
30
29
|
|
31
30
|
rb_define_method(cGyro_Signal, "initialize", Gyro_Signal_initialize, 1);
|
32
|
-
rb_define_method(cGyro_Signal, "
|
33
|
-
rb_define_method(cGyro_Signal, "stop", Gyro_Signal_stop, 0);
|
31
|
+
rb_define_method(cGyro_Signal, "await", Gyro_Signal_await, 0);
|
34
32
|
}
|
35
33
|
|
36
34
|
static const rb_data_type_t Gyro_Signal_type = {
|
@@ -47,8 +45,8 @@ static VALUE Gyro_Signal_allocate(VALUE klass) {
|
|
47
45
|
|
48
46
|
static void Gyro_Signal_mark(void *ptr) {
|
49
47
|
struct Gyro_Signal *signal = ptr;
|
50
|
-
if (signal->
|
51
|
-
rb_gc_mark(signal->
|
48
|
+
if (signal->fiber != Qnil) {
|
49
|
+
rb_gc_mark(signal->fiber);
|
52
50
|
}
|
53
51
|
}
|
54
52
|
|
@@ -72,15 +70,11 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
72
70
|
GetGyro_Signal(self, signal);
|
73
71
|
signal->signum = NUM2INT(signum);
|
74
72
|
|
75
|
-
if (rb_block_given_p()) {
|
76
|
-
signal->callback = rb_block_proc();
|
77
|
-
}
|
78
|
-
|
79
73
|
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
80
74
|
|
81
|
-
signal->active = 1;
|
82
|
-
Gyro_ref_count_incr();
|
83
|
-
ev_signal_start(EV_DEFAULT, &signal->ev_signal);
|
75
|
+
// signal->active = 1;
|
76
|
+
// Gyro_ref_count_incr();
|
77
|
+
// ev_signal_start(EV_DEFAULT, &signal->ev_signal);
|
84
78
|
|
85
79
|
return Qnil;
|
86
80
|
}
|
@@ -88,33 +82,37 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
88
82
|
void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
|
89
83
|
struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
|
90
84
|
|
91
|
-
if (signal->
|
92
|
-
|
85
|
+
if (signal->fiber != Qnil) {
|
86
|
+
VALUE fiber = signal->fiber;
|
87
|
+
|
88
|
+
ev_signal_stop(EV_DEFAULT, ev_signal);
|
89
|
+
signal->active = 0;
|
90
|
+
signal->fiber = Qnil;
|
91
|
+
Gyro_schedule_fiber(fiber, INT2NUM(signal->signum));
|
93
92
|
}
|
94
93
|
}
|
95
94
|
|
96
|
-
static VALUE
|
95
|
+
static VALUE Gyro_Signal_await(VALUE self) {
|
97
96
|
struct Gyro_Signal *signal;
|
97
|
+
VALUE ret;
|
98
|
+
|
98
99
|
GetGyro_Signal(self, signal);
|
99
100
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
signal->active = 1;
|
104
|
-
}
|
105
|
-
|
106
|
-
return self;
|
107
|
-
}
|
101
|
+
signal->fiber = rb_fiber_current();
|
102
|
+
signal->active = 1;
|
103
|
+
ev_signal_start(EV_DEFAULT, &signal->ev_signal);
|
108
104
|
|
109
|
-
|
110
|
-
struct Gyro_Signal *signal;
|
111
|
-
GetGyro_Signal(self, signal);
|
105
|
+
ret = Gyro_await();
|
112
106
|
|
113
|
-
if
|
114
|
-
|
115
|
-
|
116
|
-
signal->active
|
107
|
+
// fiber is resumed, check if resumed value is an exception
|
108
|
+
signal->fiber = Qnil;
|
109
|
+
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
110
|
+
if (signal->active) {
|
111
|
+
signal->active = 0;
|
112
|
+
ev_signal_stop(EV_DEFAULT, &signal->ev_signal);
|
113
|
+
}
|
114
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
117
115
|
}
|
118
|
-
|
119
|
-
|
120
|
-
}
|
116
|
+
else
|
117
|
+
return ret;
|
118
|
+
}
|
data/ext/gyro/timer.c
CHANGED
@@ -6,7 +6,6 @@ struct Gyro_Timer {
|
|
6
6
|
double after;
|
7
7
|
double repeat;
|
8
8
|
VALUE self;
|
9
|
-
VALUE callback;
|
10
9
|
VALUE fiber;
|
11
10
|
};
|
12
11
|
|
@@ -21,9 +20,6 @@ static size_t Gyro_Timer_size(const void *ptr);
|
|
21
20
|
/* Methods */
|
22
21
|
static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat);
|
23
22
|
|
24
|
-
static VALUE Gyro_Timer_start(VALUE self);
|
25
|
-
static VALUE Gyro_Timer_stop(VALUE self);
|
26
|
-
static VALUE Gyro_Timer_reset(VALUE self);
|
27
23
|
static VALUE Gyro_Timer_await(VALUE self);
|
28
24
|
|
29
25
|
void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
|
@@ -34,9 +30,6 @@ void Init_Gyro_Timer() {
|
|
34
30
|
rb_define_alloc_func(cGyro_Timer, Gyro_Timer_allocate);
|
35
31
|
|
36
32
|
rb_define_method(cGyro_Timer, "initialize", Gyro_Timer_initialize, 2);
|
37
|
-
rb_define_method(cGyro_Timer, "start", Gyro_Timer_start, 0);
|
38
|
-
rb_define_method(cGyro_Timer, "stop", Gyro_Timer_stop, 0);
|
39
|
-
rb_define_method(cGyro_Timer, "reset", Gyro_Timer_reset, 0);
|
40
33
|
rb_define_method(cGyro_Timer, "await", Gyro_Timer_await, 0);
|
41
34
|
}
|
42
35
|
|
@@ -54,9 +47,6 @@ static VALUE Gyro_Timer_allocate(VALUE klass) {
|
|
54
47
|
|
55
48
|
static void Gyro_Timer_mark(void *ptr) {
|
56
49
|
struct Gyro_Timer *timer = ptr;
|
57
|
-
if (timer->callback != Qnil) {
|
58
|
-
rb_gc_mark(timer->callback);
|
59
|
-
}
|
60
50
|
if (timer->fiber != Qnil) {
|
61
51
|
rb_gc_mark(timer->fiber);
|
62
52
|
}
|
@@ -83,7 +73,6 @@ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
|
|
83
73
|
GetGyro_Timer(self, timer);
|
84
74
|
|
85
75
|
timer->self = self;
|
86
|
-
timer->callback = Qnil;
|
87
76
|
timer->fiber = Qnil;
|
88
77
|
timer->after = NUM2DBL(after);
|
89
78
|
timer->repeat = NUM2DBL(repeat);
|
@@ -105,63 +94,9 @@ void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int
|
|
105
94
|
VALUE fiber = timer->fiber;
|
106
95
|
VALUE resume_value = DBL2NUM(timer->after);
|
107
96
|
|
108
|
-
ev_timer_stop(EV_DEFAULT, ev_timer);
|
109
|
-
timer->active = 0;
|
110
97
|
timer->fiber = Qnil;
|
111
98
|
Gyro_schedule_fiber(fiber, resume_value);
|
112
99
|
}
|
113
|
-
else if (timer->callback != Qnil) {
|
114
|
-
Gyro_ref_count_decr();
|
115
|
-
rb_funcall(timer->callback, ID_call, 1, Qtrue);
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
static VALUE Gyro_Timer_start(VALUE self) {
|
120
|
-
struct Gyro_Timer *timer;
|
121
|
-
GetGyro_Timer(self, timer);
|
122
|
-
|
123
|
-
if (rb_block_given_p()) {
|
124
|
-
Gyro_ref_count_incr();
|
125
|
-
timer->callback = rb_block_proc();
|
126
|
-
}
|
127
|
-
|
128
|
-
if (!timer->active) {
|
129
|
-
ev_timer_start(EV_DEFAULT, &timer->ev_timer);
|
130
|
-
timer->active = 1;
|
131
|
-
}
|
132
|
-
|
133
|
-
return self;
|
134
|
-
}
|
135
|
-
|
136
|
-
static VALUE Gyro_Timer_stop(VALUE self) {
|
137
|
-
struct Gyro_Timer *timer;
|
138
|
-
GetGyro_Timer(self, timer);
|
139
|
-
|
140
|
-
if (timer->active) {
|
141
|
-
ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
|
142
|
-
timer->active = 0;
|
143
|
-
}
|
144
|
-
|
145
|
-
return self;
|
146
|
-
}
|
147
|
-
|
148
|
-
static VALUE Gyro_Timer_reset(VALUE self) {
|
149
|
-
struct Gyro_Timer *timer;
|
150
|
-
int prev_active;
|
151
|
-
GetGyro_Timer(self, timer);
|
152
|
-
|
153
|
-
prev_active = timer->active;
|
154
|
-
|
155
|
-
if (prev_active) {
|
156
|
-
ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
|
157
|
-
}
|
158
|
-
ev_timer_set(&timer->ev_timer, timer->after, timer->repeat);
|
159
|
-
ev_timer_start(EV_DEFAULT, &timer->ev_timer);
|
160
|
-
if (!prev_active) {
|
161
|
-
timer->active = 1;
|
162
|
-
}
|
163
|
-
|
164
|
-
return self;
|
165
100
|
}
|
166
101
|
|
167
102
|
static VALUE Gyro_Timer_await(VALUE self) {
|
@@ -171,19 +106,17 @@ static VALUE Gyro_Timer_await(VALUE self) {
|
|
171
106
|
GetGyro_Timer(self, timer);
|
172
107
|
|
173
108
|
timer->fiber = rb_fiber_current();
|
174
|
-
timer->active
|
175
|
-
|
109
|
+
if (timer->active != 1) {
|
110
|
+
timer->active = 1;
|
111
|
+
ev_timer_start(EV_DEFAULT, &timer->ev_timer);
|
112
|
+
}
|
176
113
|
|
177
|
-
ret =
|
114
|
+
ret = Gyro_await();
|
178
115
|
|
179
116
|
// fiber is resumed, check if resumed value is an exception
|
180
117
|
timer->fiber = Qnil;
|
181
118
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
182
|
-
|
183
|
-
timer->active = 0;
|
184
|
-
ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
|
185
|
-
}
|
186
|
-
return rb_funcall(ret, ID_raise, 1, ret);
|
119
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
187
120
|
}
|
188
121
|
else
|
189
122
|
return ret;
|
data/lib/polyphony.rb
CHANGED
@@ -12,6 +12,9 @@ import './polyphony/extensions/io'
|
|
12
12
|
|
13
13
|
# Main Polyphony API
|
14
14
|
module Polyphony
|
15
|
+
GlobalAPI = import './polyphony/core/global_api'
|
16
|
+
::Object.include GlobalAPI
|
17
|
+
|
15
18
|
exceptions = import './polyphony/core/exceptions'
|
16
19
|
Cancel = exceptions::Cancel
|
17
20
|
MoveOn = exceptions::MoveOn
|
@@ -56,13 +59,6 @@ module Polyphony
|
|
56
59
|
pid = Kernel.fork do
|
57
60
|
setup_forked_process
|
58
61
|
block.()
|
59
|
-
|
60
|
-
# We cannot simply depend on the at_exit block (see polyphony/auto_run)
|
61
|
-
# to yield to the reactor fiber. Doing that will raise a FiberError
|
62
|
-
# complaining: "fiber called across stack rewinding barrier". Apparently
|
63
|
-
# this is a bug in Ruby, so the workaround is to yield just before
|
64
|
-
# exiting.
|
65
|
-
suspend
|
66
62
|
end
|
67
63
|
Gyro.reset!
|
68
64
|
pid
|
@@ -71,14 +67,16 @@ module Polyphony
|
|
71
67
|
def reset!
|
72
68
|
# Fiber.root.scheduled_value = nil
|
73
69
|
Gyro.reset!
|
70
|
+
Coprocess.map.clear
|
71
|
+
Fiber.set_root_fiber
|
74
72
|
end
|
75
73
|
|
76
74
|
private
|
77
75
|
|
78
76
|
def setup_forked_process
|
77
|
+
Coprocess.map.delete Fiber.root
|
79
78
|
Gyro.post_fork
|
80
79
|
Fiber.set_root_fiber
|
81
|
-
Fiber.current.coprocess = Coprocess.new(Fiber.current)
|
82
80
|
end
|
83
81
|
end
|
84
82
|
end
|
@@ -10,6 +10,8 @@ Exceptions = import('./exceptions')
|
|
10
10
|
class CancelScope
|
11
11
|
def initialize(opts = {}, &block)
|
12
12
|
@opts = opts
|
13
|
+
@fibers = []
|
14
|
+
start_timeout_waiter if @opts[:timeout]
|
13
15
|
call(&block) if block
|
14
16
|
end
|
15
17
|
|
@@ -19,33 +21,49 @@ class CancelScope
|
|
19
21
|
|
20
22
|
def cancel!
|
21
23
|
@cancelled = true
|
22
|
-
@
|
23
|
-
|
24
|
+
@fibers.each do |f|
|
25
|
+
f.cancelled = true
|
26
|
+
f.schedule error_class.new(self, @opts[:value])
|
27
|
+
end
|
28
|
+
@on_cancel&.()
|
24
29
|
end
|
25
30
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
|
31
|
+
def start_timeout_waiter
|
32
|
+
@timeout_waiter = spin do
|
33
|
+
sleep @opts[:timeout]
|
34
|
+
@timeout_waiter = nil
|
35
|
+
cancel!
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
|
-
def
|
32
|
-
@
|
39
|
+
def stop_timeout_waiter
|
40
|
+
return unless @timeout_waiter
|
41
|
+
|
42
|
+
@timeout_waiter.stop
|
43
|
+
@timeout_waiter = nil
|
33
44
|
end
|
34
45
|
|
35
|
-
def
|
36
|
-
@
|
46
|
+
def reset_timeout
|
47
|
+
return unless @timeout_waiter
|
48
|
+
|
49
|
+
@timeout_waiter.stop
|
50
|
+
start_timeout_waiter
|
37
51
|
end
|
38
52
|
|
53
|
+
# def disable
|
54
|
+
# @timeout&.stop
|
55
|
+
# end
|
56
|
+
|
39
57
|
def call
|
40
|
-
|
41
|
-
@
|
42
|
-
|
58
|
+
fiber = Fiber.current
|
59
|
+
@fibers << fiber
|
60
|
+
fiber.cancelled = nil
|
43
61
|
yield self
|
44
62
|
rescue Exceptions::MoveOn => e
|
45
63
|
e.scope == self ? e.value : raise(e)
|
46
64
|
ensure
|
47
|
-
@
|
48
|
-
|
65
|
+
@fibers.delete fiber
|
66
|
+
stop_timeout_waiter if @fibers.empty? && @timeout_waiter
|
49
67
|
end
|
50
68
|
|
51
69
|
def on_cancel(&block)
|
@@ -55,11 +73,4 @@ class CancelScope
|
|
55
73
|
def cancelled?
|
56
74
|
@cancelled
|
57
75
|
end
|
58
|
-
|
59
|
-
def protect(&block)
|
60
|
-
@fiber.cancelled = false
|
61
|
-
block.()
|
62
|
-
ensure
|
63
|
-
@fiber.cancelled = @cancelled
|
64
|
-
end
|
65
76
|
end
|