polyphony 0.19 → 0.20
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/.gitignore +1 -1
- data/.rubocop.yml +87 -1
- data/CHANGELOG.md +35 -0
- data/Gemfile.lock +17 -6
- data/README.md +200 -139
- data/Rakefile +4 -4
- data/TODO.md +35 -7
- data/bin/poly +11 -0
- data/docs/getting-started/getting-started.md +1 -1
- data/docs/summary.md +3 -0
- data/docs/technical-overview/exception-handling.md +94 -0
- data/docs/technical-overview/fiber-scheduling.md +99 -0
- data/examples/core/cancel.rb +8 -4
- data/examples/core/channel_echo.rb +18 -17
- data/examples/core/defer.rb +12 -0
- data/examples/core/enumerator.rb +4 -4
- data/examples/core/fiber_error.rb +9 -0
- data/examples/core/fiber_error_with_backtrace.rb +73 -0
- data/examples/core/fork.rb +6 -6
- data/examples/core/genserver.rb +16 -8
- data/examples/core/lock.rb +3 -3
- data/examples/core/move_on.rb +4 -3
- data/examples/core/move_on_twice.rb +5 -5
- data/examples/core/move_on_with_ensure.rb +8 -11
- data/examples/core/move_on_with_value.rb +14 -0
- data/examples/core/{multiple_spawn.rb → multiple_spin.rb} +5 -5
- data/examples/core/nested_cancel.rb +5 -5
- data/examples/core/{nested_multiple_spawn.rb → nested_multiple_spin.rb} +6 -6
- data/examples/core/nested_spin.rb +17 -0
- data/examples/core/pingpong.rb +21 -0
- data/examples/core/pulse.rb +4 -5
- data/examples/core/resource.rb +6 -4
- data/examples/core/resource_cancel.rb +6 -9
- data/examples/core/resource_delegate.rb +3 -3
- data/examples/core/sleep.rb +3 -3
- data/examples/core/sleep_spin.rb +19 -0
- data/examples/core/snooze.rb +32 -0
- data/examples/core/spin.rb +14 -0
- data/examples/core/{spawn_cancel.rb → spin_cancel.rb} +6 -7
- data/examples/core/spin_error.rb +17 -0
- data/examples/core/spin_error_backtrace.rb +30 -0
- data/examples/core/spin_uncaught_error.rb +15 -0
- data/examples/core/supervisor.rb +8 -8
- data/examples/core/supervisor_with_cancel_scope.rb +7 -7
- data/examples/core/supervisor_with_error.rb +8 -8
- data/examples/core/supervisor_with_manual_move_on.rb +6 -7
- data/examples/core/suspend.rb +13 -0
- data/examples/core/thread.rb +1 -1
- data/examples/core/thread_cancel.rb +9 -11
- data/examples/core/thread_pool.rb +18 -14
- data/examples/core/throttle.rb +7 -7
- data/examples/core/timeout.rb +3 -3
- data/examples/fs/read.rb +7 -9
- data/examples/http/config.ru +7 -3
- data/examples/http/cuba.ru +22 -0
- data/examples/http/happy_eyeballs.rb +6 -4
- data/examples/http/http_client.rb +1 -1
- data/examples/http/http_get.rb +1 -1
- data/examples/http/http_parse_experiment.rb +21 -16
- data/examples/http/http_proxy.rb +28 -26
- data/examples/http/http_server.rb +10 -10
- data/examples/http/http_server_forked.rb +6 -5
- data/examples/http/http_server_throttled.rb +3 -3
- data/examples/http/http_ws_server.rb +11 -11
- data/examples/http/https_raw_client.rb +1 -1
- data/examples/http/https_server.rb +8 -8
- data/examples/http/https_wss_server.rb +13 -11
- data/examples/http/rack_server.rb +2 -2
- data/examples/http/rack_server_https.rb +4 -4
- data/examples/http/rack_server_https_forked.rb +5 -5
- data/examples/http/websocket_secure_server.rb +6 -6
- data/examples/http/websocket_server.rb +5 -5
- data/examples/interfaces/pg_client.rb +4 -4
- data/examples/interfaces/pg_pool.rb +13 -6
- data/examples/interfaces/pg_transaction.rb +5 -4
- data/examples/interfaces/redis_channels.rb +15 -11
- data/examples/interfaces/redis_client.rb +2 -2
- data/examples/interfaces/redis_pubsub.rb +2 -1
- data/examples/interfaces/redis_pubsub_perf.rb +13 -9
- data/examples/io/backticks.rb +11 -0
- data/examples/io/cat.rb +4 -5
- data/examples/io/echo_client.rb +9 -4
- data/examples/io/echo_client_from_stdin.rb +20 -0
- data/examples/io/echo_pipe.rb +7 -8
- data/examples/io/echo_server.rb +8 -6
- data/examples/io/echo_server_with_timeout.rb +13 -10
- data/examples/io/echo_stdin.rb +3 -3
- data/examples/io/httparty.rb +2 -2
- data/examples/io/httparty_multi.rb +8 -4
- data/examples/io/httparty_threaded.rb +6 -2
- data/examples/io/io_read.rb +2 -2
- data/examples/io/irb.rb +16 -4
- data/examples/io/net-http.rb +3 -3
- data/examples/io/open.rb +17 -0
- data/examples/io/system.rb +3 -3
- data/examples/io/tcpserver.rb +15 -0
- data/examples/io/tcpsocket.rb +6 -5
- data/examples/performance/multi_snooze.rb +29 -0
- data/examples/performance/{perf_snooze.rb → snooze.rb} +7 -5
- data/examples/performance/snooze_raw.rb +39 -0
- data/ext/gyro/async.c +165 -0
- data/ext/gyro/child.c +167 -0
- data/ext/{ev → gyro}/extconf.rb +4 -3
- data/ext/gyro/gyro.c +316 -0
- data/ext/{ev/ev.h → gyro/gyro.h} +12 -7
- data/ext/gyro/gyro_ext.c +23 -0
- data/ext/{ev → gyro}/io.c +65 -57
- data/ext/{ev → gyro}/libev.h +0 -0
- data/ext/gyro/signal.c +117 -0
- data/ext/{ev → gyro}/socket.c +61 -6
- data/ext/gyro/timer.c +199 -0
- data/ext/libev/Changes +35 -0
- data/ext/libev/README +2 -1
- data/ext/libev/ev.c +213 -151
- data/ext/libev/ev.h +95 -88
- data/ext/libev/ev_epoll.c +26 -15
- data/ext/libev/ev_kqueue.c +11 -5
- data/ext/libev/ev_linuxaio.c +642 -0
- data/ext/libev/ev_poll.c +13 -8
- data/ext/libev/ev_port.c +5 -2
- data/ext/libev/ev_vars.h +14 -3
- data/ext/libev/ev_wrap.h +16 -0
- data/lib/ev_ext.bundle +0 -0
- data/lib/polyphony.rb +46 -50
- data/lib/polyphony/auto_run.rb +12 -0
- data/lib/polyphony/core/cancel_scope.rb +11 -7
- data/lib/polyphony/core/channel.rb +16 -9
- data/lib/polyphony/core/coprocess.rb +101 -51
- data/lib/polyphony/core/exceptions.rb +14 -12
- data/lib/polyphony/core/resource_pool.rb +21 -8
- data/lib/polyphony/core/supervisor.rb +10 -5
- data/lib/polyphony/core/sync.rb +7 -6
- data/lib/polyphony/core/thread.rb +4 -4
- data/lib/polyphony/core/thread_pool.rb +4 -4
- data/lib/polyphony/core/throttler.rb +6 -4
- data/lib/polyphony/extensions/core.rb +253 -0
- data/lib/polyphony/extensions/io.rb +28 -16
- data/lib/polyphony/extensions/openssl.rb +2 -1
- data/lib/polyphony/extensions/socket.rb +47 -52
- data/lib/polyphony/http.rb +4 -3
- data/lib/polyphony/http/agent.rb +68 -57
- data/lib/polyphony/http/server.rb +5 -5
- data/lib/polyphony/http/server/http1.rb +268 -0
- data/lib/polyphony/http/server/http2.rb +62 -0
- data/lib/polyphony/http/server/http2_stream.rb +104 -0
- data/lib/polyphony/http/server/rack.rb +64 -0
- data/lib/polyphony/http/server/request.rb +119 -0
- data/lib/polyphony/net.rb +26 -15
- data/lib/polyphony/postgres.rb +17 -13
- data/lib/polyphony/redis.rb +16 -15
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony/websocket.rb +11 -4
- data/polyphony.gemspec +13 -9
- data/test/eg.rb +27 -0
- data/test/helper.rb +25 -0
- data/test/run.rb +5 -0
- data/test/test_async.rb +33 -0
- data/test/test_coprocess.rb +239 -77
- data/test/test_core.rb +95 -61
- data/test/test_gyro.rb +148 -0
- data/test/test_http_server.rb +313 -0
- data/test/test_io.rb +79 -27
- data/test/test_kernel.rb +22 -12
- data/test/test_signal.rb +36 -0
- data/test/test_timer.rb +24 -0
- metadata +89 -33
- data/examples/core/nested_async.rb +0 -17
- data/examples/core/next_tick.rb +0 -12
- data/examples/core/sleep_spawn.rb +0 -19
- data/examples/core/spawn.rb +0 -14
- data/examples/core/spawn_error.rb +0 -28
- data/examples/performance/perf_multi_snooze.rb +0 -21
- data/ext/ev/async.c +0 -168
- data/ext/ev/child.c +0 -169
- data/ext/ev/ev_ext.c +0 -23
- data/ext/ev/ev_module.c +0 -242
- data/ext/ev/signal.c +0 -119
- data/ext/ev/timer.c +0 -197
- data/lib/polyphony/core/fiber_pool.rb +0 -98
- data/lib/polyphony/extensions/kernel.rb +0 -169
- data/lib/polyphony/http/http1_adapter.rb +0 -254
- data/lib/polyphony/http/http2_adapter.rb +0 -157
- data/lib/polyphony/http/rack.rb +0 -25
- data/lib/polyphony/http/request.rb +0 -66
- data/test/test_ev.rb +0 -110
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'polyphony'
|
5
|
-
|
6
|
-
spin do
|
7
|
-
puts "going to sleep"
|
8
|
-
result = async do
|
9
|
-
async do
|
10
|
-
async do
|
11
|
-
puts "Fiber count: #{Polyphony::FiberPool.size}"
|
12
|
-
sleep(1)
|
13
|
-
end.await
|
14
|
-
end.await
|
15
|
-
end.await
|
16
|
-
puts "result: #{result}"
|
17
|
-
end
|
data/examples/core/next_tick.rb
DELETED
data/examples/core/spawn.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'polyphony'
|
5
|
-
|
6
|
-
Polyphony.debug = true
|
7
|
-
|
8
|
-
def error(t)
|
9
|
-
raise "hello #{t}"
|
10
|
-
end
|
11
|
-
|
12
|
-
def spin_with_error
|
13
|
-
spin { error(2) }
|
14
|
-
end
|
15
|
-
|
16
|
-
spin do
|
17
|
-
error(1)
|
18
|
-
rescue => e
|
19
|
-
e.cleanup_backtrace
|
20
|
-
puts "error: #{e.inspect}"
|
21
|
-
puts "backtrace:"
|
22
|
-
puts e.backtrace.reverse.join("\n")
|
23
|
-
puts
|
24
|
-
end
|
25
|
-
|
26
|
-
spin_with_error
|
27
|
-
|
28
|
-
puts "done coprocing"
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'polyphony'
|
5
|
-
|
6
|
-
ITERATIONS = 1_000
|
7
|
-
FIBERS = 1_000
|
8
|
-
|
9
|
-
spin do
|
10
|
-
count = 0
|
11
|
-
t0 = Time.now
|
12
|
-
supervise do |s|
|
13
|
-
FIBERS.times do
|
14
|
-
s.spin do
|
15
|
-
ITERATIONS.times { snooze; count += 1 }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
dt = Time.now - t0
|
20
|
-
puts "count: #{count} #{count / dt.to_f}/s"
|
21
|
-
end
|
data/ext/ev/async.c
DELETED
@@ -1,168 +0,0 @@
|
|
1
|
-
#include "ev.h"
|
2
|
-
|
3
|
-
struct EV_Async {
|
4
|
-
struct ev_async ev_async;
|
5
|
-
int active;
|
6
|
-
VALUE callback;
|
7
|
-
VALUE fiber;
|
8
|
-
};
|
9
|
-
|
10
|
-
static VALUE mEV = Qnil;
|
11
|
-
static VALUE cEV_Async = Qnil;
|
12
|
-
|
13
|
-
/* Allocator/deallocator */
|
14
|
-
static VALUE EV_Async_allocate(VALUE klass);
|
15
|
-
static void EV_Async_mark(void *ptr);
|
16
|
-
static void EV_Async_free(void *ptr);
|
17
|
-
static size_t EV_Async_size(const void *ptr);
|
18
|
-
|
19
|
-
/* Methods */
|
20
|
-
static VALUE EV_Async_initialize(VALUE self);
|
21
|
-
|
22
|
-
static VALUE EV_Async_start(VALUE self);
|
23
|
-
static VALUE EV_Async_stop(VALUE self);
|
24
|
-
static VALUE EV_Async_signal(VALUE self);
|
25
|
-
static VALUE EV_Async_await(VALUE self);
|
26
|
-
|
27
|
-
void EV_Async_callback(ev_loop *ev_loop, struct ev_async *async, int revents);
|
28
|
-
|
29
|
-
/* async encapsulates an async watcher */
|
30
|
-
void Init_EV_Async() {
|
31
|
-
mEV = rb_define_module("EV");
|
32
|
-
|
33
|
-
cEV_Async = rb_define_class_under(mEV, "Async", rb_cData);
|
34
|
-
rb_define_alloc_func(cEV_Async, EV_Async_allocate);
|
35
|
-
|
36
|
-
rb_define_method(cEV_Async, "initialize", EV_Async_initialize, 0);
|
37
|
-
rb_define_method(cEV_Async, "start", EV_Async_start, 0);
|
38
|
-
rb_define_method(cEV_Async, "stop", EV_Async_stop, 0);
|
39
|
-
rb_define_method(cEV_Async, "signal!", EV_Async_signal, 0);
|
40
|
-
rb_define_method(cEV_Async, "await", EV_Async_await, 0);
|
41
|
-
}
|
42
|
-
|
43
|
-
static const rb_data_type_t EV_Async_type = {
|
44
|
-
"EV_Async",
|
45
|
-
{EV_Async_mark, EV_Async_free, EV_Async_size,},
|
46
|
-
0, 0,
|
47
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
48
|
-
};
|
49
|
-
|
50
|
-
static VALUE EV_Async_allocate(VALUE klass) {
|
51
|
-
struct EV_Async *async = (struct EV_Async *)xmalloc(sizeof(struct EV_Async));
|
52
|
-
return TypedData_Wrap_Struct(klass, &EV_Async_type, async);
|
53
|
-
}
|
54
|
-
|
55
|
-
static void EV_Async_mark(void *ptr) {
|
56
|
-
struct EV_Async *async = ptr;
|
57
|
-
if (async->callback != Qnil) {
|
58
|
-
rb_gc_mark(async->callback);
|
59
|
-
}
|
60
|
-
if (async->fiber != Qnil) {
|
61
|
-
rb_gc_mark(async->fiber);
|
62
|
-
}
|
63
|
-
}
|
64
|
-
|
65
|
-
static void EV_Async_free(void *ptr) {
|
66
|
-
struct EV_Async *async = ptr;
|
67
|
-
ev_async_stop(EV_DEFAULT, &async->ev_async);
|
68
|
-
xfree(async);
|
69
|
-
}
|
70
|
-
|
71
|
-
static size_t EV_Async_size(const void *ptr) {
|
72
|
-
return sizeof(struct EV_Async);
|
73
|
-
}
|
74
|
-
|
75
|
-
#define GetEV_Async(obj, async) \
|
76
|
-
TypedData_Get_Struct((obj), struct EV_Async, &EV_Async_type, (async))
|
77
|
-
|
78
|
-
static VALUE EV_Async_initialize(VALUE self) {
|
79
|
-
struct EV_Async *async;
|
80
|
-
GetEV_Async(self, async);
|
81
|
-
|
82
|
-
if (rb_block_given_p()) {
|
83
|
-
async->callback = rb_block_proc();
|
84
|
-
}
|
85
|
-
async->fiber = Qnil;
|
86
|
-
|
87
|
-
ev_async_init(&async->ev_async, EV_Async_callback);
|
88
|
-
|
89
|
-
async->active = 1;
|
90
|
-
ev_async_start(EV_DEFAULT, &async->ev_async);
|
91
|
-
|
92
|
-
return Qnil;
|
93
|
-
}
|
94
|
-
|
95
|
-
void EV_Async_callback(ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
|
96
|
-
VALUE fiber;
|
97
|
-
struct EV_Async *async = (struct EV_Async*)ev_async;
|
98
|
-
|
99
|
-
if (async->fiber != Qnil) {
|
100
|
-
async->active = 0;
|
101
|
-
fiber = async->fiber;
|
102
|
-
async->fiber = Qnil;
|
103
|
-
SCHEDULE_FIBER(fiber, 0);
|
104
|
-
}
|
105
|
-
else if (async->callback != Qnil) {
|
106
|
-
rb_funcall(async->callback, ID_call, 1, Qtrue);
|
107
|
-
}
|
108
|
-
}
|
109
|
-
|
110
|
-
static VALUE EV_Async_start(VALUE self) {
|
111
|
-
struct EV_Async *async;
|
112
|
-
GetEV_Async(self, async);
|
113
|
-
|
114
|
-
if (!async->active) {
|
115
|
-
ev_async_start(EV_DEFAULT, &async->ev_async);
|
116
|
-
async->active = 1;
|
117
|
-
}
|
118
|
-
|
119
|
-
return self;
|
120
|
-
}
|
121
|
-
|
122
|
-
static VALUE EV_Async_stop(VALUE self) {
|
123
|
-
struct EV_Async *async;
|
124
|
-
GetEV_Async(self, async);
|
125
|
-
|
126
|
-
if (async->active) {
|
127
|
-
ev_async_stop(EV_DEFAULT, &async->ev_async);
|
128
|
-
async->active = 0;
|
129
|
-
}
|
130
|
-
|
131
|
-
return self;
|
132
|
-
}
|
133
|
-
|
134
|
-
static VALUE EV_Async_signal(VALUE self) {
|
135
|
-
struct EV_Async *async;
|
136
|
-
GetEV_Async(self, async);
|
137
|
-
|
138
|
-
ev_async_send(EV_DEFAULT, &async->ev_async);
|
139
|
-
|
140
|
-
return Qnil;
|
141
|
-
}
|
142
|
-
|
143
|
-
static VALUE EV_Async_await(VALUE self) {
|
144
|
-
struct EV_Async *async;
|
145
|
-
VALUE ret;
|
146
|
-
|
147
|
-
GetEV_Async(self, async);
|
148
|
-
|
149
|
-
async->fiber = rb_fiber_current();
|
150
|
-
if (!async->active) {
|
151
|
-
async->active = 1;
|
152
|
-
ev_async_start(EV_DEFAULT, &async->ev_async);
|
153
|
-
}
|
154
|
-
|
155
|
-
ret = YIELD_TO_REACTOR();
|
156
|
-
|
157
|
-
// fiber is resumed
|
158
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
159
|
-
if (async->active) {
|
160
|
-
async->active = 0;
|
161
|
-
ev_async_stop(EV_DEFAULT, &async->ev_async);
|
162
|
-
}
|
163
|
-
return rb_funcall(ret, ID_raise, 1, ret);
|
164
|
-
}
|
165
|
-
else {
|
166
|
-
return Qnil;
|
167
|
-
}
|
168
|
-
}
|
data/ext/ev/child.c
DELETED
@@ -1,169 +0,0 @@
|
|
1
|
-
#include "ev.h"
|
2
|
-
|
3
|
-
struct EV_Child {
|
4
|
-
struct ev_child ev_child;
|
5
|
-
int active;
|
6
|
-
int pid;
|
7
|
-
VALUE self;
|
8
|
-
VALUE callback;
|
9
|
-
VALUE fiber;
|
10
|
-
};
|
11
|
-
|
12
|
-
static VALUE mEV = Qnil;
|
13
|
-
static VALUE cEV_Child = Qnil;
|
14
|
-
|
15
|
-
/* Allocator/deallocator */
|
16
|
-
static VALUE EV_Child_allocate(VALUE klass);
|
17
|
-
static void EV_Child_mark(void *ptr);
|
18
|
-
static void EV_Child_free(void *ptr);
|
19
|
-
static size_t EV_Child_size(const void *ptr);
|
20
|
-
|
21
|
-
/* Methods */
|
22
|
-
static VALUE EV_Child_initialize(VALUE self, VALUE pid);
|
23
|
-
|
24
|
-
static VALUE EV_Child_start(VALUE self);
|
25
|
-
static VALUE EV_Child_stop(VALUE self);
|
26
|
-
static VALUE EV_Child_await(VALUE self);
|
27
|
-
|
28
|
-
void EV_Child_callback(ev_loop *ev_loop, struct ev_child *child, int revents);
|
29
|
-
|
30
|
-
/* Child encapsulates an child watcher */
|
31
|
-
void Init_EV_Child() {
|
32
|
-
mEV = rb_define_module("EV");
|
33
|
-
cEV_Child = rb_define_class_under(mEV, "Child", rb_cData);
|
34
|
-
rb_define_alloc_func(cEV_Child, EV_Child_allocate);
|
35
|
-
|
36
|
-
rb_define_method(cEV_Child, "initialize", EV_Child_initialize, 1);
|
37
|
-
rb_define_method(cEV_Child, "start", EV_Child_start, 0);
|
38
|
-
rb_define_method(cEV_Child, "stop", EV_Child_stop, 0);
|
39
|
-
rb_define_method(cEV_Child, "await", EV_Child_await, 0);
|
40
|
-
}
|
41
|
-
|
42
|
-
static const rb_data_type_t EV_Child_type = {
|
43
|
-
"EV_Child",
|
44
|
-
{EV_Child_mark, EV_Child_free, EV_Child_size,},
|
45
|
-
0, 0,
|
46
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
47
|
-
};
|
48
|
-
|
49
|
-
static VALUE EV_Child_allocate(VALUE klass) {
|
50
|
-
struct EV_Child *child = (struct EV_Child *)xmalloc(sizeof(struct EV_Child));
|
51
|
-
return TypedData_Wrap_Struct(klass, &EV_Child_type, child);
|
52
|
-
}
|
53
|
-
|
54
|
-
static void EV_Child_mark(void *ptr) {
|
55
|
-
struct EV_Child *child = ptr;
|
56
|
-
if (child->callback != Qnil) {
|
57
|
-
rb_gc_mark(child->callback);
|
58
|
-
}
|
59
|
-
if (child->fiber != Qnil) {
|
60
|
-
rb_gc_mark(child->fiber);
|
61
|
-
}
|
62
|
-
}
|
63
|
-
|
64
|
-
static void EV_Child_free(void *ptr) {
|
65
|
-
struct EV_Child *child = ptr;
|
66
|
-
if (child->active) {
|
67
|
-
ev_child_stop(EV_DEFAULT, &child->ev_child);
|
68
|
-
}
|
69
|
-
xfree(child);
|
70
|
-
}
|
71
|
-
|
72
|
-
static size_t EV_Child_size(const void *ptr) {
|
73
|
-
return sizeof(struct EV_Child);
|
74
|
-
}
|
75
|
-
|
76
|
-
#define GetEV_Child(obj, child) \
|
77
|
-
TypedData_Get_Struct((obj), struct EV_Child, &EV_Child_type, (child))
|
78
|
-
|
79
|
-
static VALUE EV_Child_initialize(VALUE self, VALUE pid) {
|
80
|
-
struct EV_Child *child;
|
81
|
-
|
82
|
-
GetEV_Child(self, child);
|
83
|
-
|
84
|
-
child->self = self;
|
85
|
-
child->callback = Qnil;
|
86
|
-
child->fiber = Qnil;
|
87
|
-
child->pid = NUM2INT(pid);
|
88
|
-
child->active = 0;
|
89
|
-
|
90
|
-
ev_child_init(&child->ev_child, EV_Child_callback, child->pid, 0);
|
91
|
-
|
92
|
-
return Qnil;
|
93
|
-
}
|
94
|
-
|
95
|
-
void EV_Child_callback(ev_loop *ev_loop, struct ev_child *ev_child, int revents) {
|
96
|
-
VALUE fiber;
|
97
|
-
VALUE resume_value;
|
98
|
-
struct EV_Child *child = (struct EV_Child*)ev_child;
|
99
|
-
resume_value = INT2NUM(child->pid);
|
100
|
-
|
101
|
-
child->active = 0;
|
102
|
-
ev_child_stop(EV_DEFAULT, ev_child);
|
103
|
-
EV_del_watcher_ref(child->self);
|
104
|
-
|
105
|
-
if (child->fiber != Qnil) {
|
106
|
-
fiber = child->fiber;
|
107
|
-
child->fiber = Qnil;
|
108
|
-
SCHEDULE_FIBER(fiber, 1, resume_value);
|
109
|
-
}
|
110
|
-
else if (child->callback != Qnil) {
|
111
|
-
rb_funcall(child->callback, ID_call, 1, resume_value);
|
112
|
-
}
|
113
|
-
}
|
114
|
-
|
115
|
-
static VALUE EV_Child_start(VALUE self) {
|
116
|
-
struct EV_Child *child;
|
117
|
-
GetEV_Child(self, child);
|
118
|
-
|
119
|
-
if (rb_block_given_p()) {
|
120
|
-
child->callback = rb_block_proc();
|
121
|
-
}
|
122
|
-
|
123
|
-
if (!child->active) {
|
124
|
-
ev_child_start(EV_DEFAULT, &child->ev_child);
|
125
|
-
child->active = 1;
|
126
|
-
EV_add_watcher_ref(self);
|
127
|
-
}
|
128
|
-
|
129
|
-
return self;
|
130
|
-
}
|
131
|
-
|
132
|
-
static VALUE EV_Child_stop(VALUE self) {
|
133
|
-
struct EV_Child *child;
|
134
|
-
GetEV_Child(self, child);
|
135
|
-
|
136
|
-
if (child->active) {
|
137
|
-
ev_child_stop(EV_DEFAULT, &child->ev_child);
|
138
|
-
child->active = 0;
|
139
|
-
EV_del_watcher_ref(self);
|
140
|
-
}
|
141
|
-
|
142
|
-
return self;
|
143
|
-
}
|
144
|
-
|
145
|
-
static VALUE EV_Child_await(VALUE self) {
|
146
|
-
struct EV_Child *child;
|
147
|
-
VALUE ret;
|
148
|
-
|
149
|
-
GetEV_Child(self, child);
|
150
|
-
|
151
|
-
child->fiber = rb_fiber_current();
|
152
|
-
child->active = 1;
|
153
|
-
ev_child_start(EV_DEFAULT, &child->ev_child);
|
154
|
-
EV_add_watcher_ref(self);
|
155
|
-
|
156
|
-
ret = YIELD_TO_REACTOR();
|
157
|
-
|
158
|
-
// fiber is resumed, check if resumed value is an exception
|
159
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
160
|
-
if (child->active) {
|
161
|
-
child->active = 0;
|
162
|
-
ev_child_stop(EV_DEFAULT, &child->ev_child);
|
163
|
-
}
|
164
|
-
return rb_funcall(ret, ID_raise, 1, ret);
|
165
|
-
}
|
166
|
-
else {
|
167
|
-
return ret;
|
168
|
-
}
|
169
|
-
}
|