polyphony 0.22 → 0.23
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/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
|