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.
Files changed (186) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.rubocop.yml +87 -1
  4. data/CHANGELOG.md +35 -0
  5. data/Gemfile.lock +17 -6
  6. data/README.md +200 -139
  7. data/Rakefile +4 -4
  8. data/TODO.md +35 -7
  9. data/bin/poly +11 -0
  10. data/docs/getting-started/getting-started.md +1 -1
  11. data/docs/summary.md +3 -0
  12. data/docs/technical-overview/exception-handling.md +94 -0
  13. data/docs/technical-overview/fiber-scheduling.md +99 -0
  14. data/examples/core/cancel.rb +8 -4
  15. data/examples/core/channel_echo.rb +18 -17
  16. data/examples/core/defer.rb +12 -0
  17. data/examples/core/enumerator.rb +4 -4
  18. data/examples/core/fiber_error.rb +9 -0
  19. data/examples/core/fiber_error_with_backtrace.rb +73 -0
  20. data/examples/core/fork.rb +6 -6
  21. data/examples/core/genserver.rb +16 -8
  22. data/examples/core/lock.rb +3 -3
  23. data/examples/core/move_on.rb +4 -3
  24. data/examples/core/move_on_twice.rb +5 -5
  25. data/examples/core/move_on_with_ensure.rb +8 -11
  26. data/examples/core/move_on_with_value.rb +14 -0
  27. data/examples/core/{multiple_spawn.rb → multiple_spin.rb} +5 -5
  28. data/examples/core/nested_cancel.rb +5 -5
  29. data/examples/core/{nested_multiple_spawn.rb → nested_multiple_spin.rb} +6 -6
  30. data/examples/core/nested_spin.rb +17 -0
  31. data/examples/core/pingpong.rb +21 -0
  32. data/examples/core/pulse.rb +4 -5
  33. data/examples/core/resource.rb +6 -4
  34. data/examples/core/resource_cancel.rb +6 -9
  35. data/examples/core/resource_delegate.rb +3 -3
  36. data/examples/core/sleep.rb +3 -3
  37. data/examples/core/sleep_spin.rb +19 -0
  38. data/examples/core/snooze.rb +32 -0
  39. data/examples/core/spin.rb +14 -0
  40. data/examples/core/{spawn_cancel.rb → spin_cancel.rb} +6 -7
  41. data/examples/core/spin_error.rb +17 -0
  42. data/examples/core/spin_error_backtrace.rb +30 -0
  43. data/examples/core/spin_uncaught_error.rb +15 -0
  44. data/examples/core/supervisor.rb +8 -8
  45. data/examples/core/supervisor_with_cancel_scope.rb +7 -7
  46. data/examples/core/supervisor_with_error.rb +8 -8
  47. data/examples/core/supervisor_with_manual_move_on.rb +6 -7
  48. data/examples/core/suspend.rb +13 -0
  49. data/examples/core/thread.rb +1 -1
  50. data/examples/core/thread_cancel.rb +9 -11
  51. data/examples/core/thread_pool.rb +18 -14
  52. data/examples/core/throttle.rb +7 -7
  53. data/examples/core/timeout.rb +3 -3
  54. data/examples/fs/read.rb +7 -9
  55. data/examples/http/config.ru +7 -3
  56. data/examples/http/cuba.ru +22 -0
  57. data/examples/http/happy_eyeballs.rb +6 -4
  58. data/examples/http/http_client.rb +1 -1
  59. data/examples/http/http_get.rb +1 -1
  60. data/examples/http/http_parse_experiment.rb +21 -16
  61. data/examples/http/http_proxy.rb +28 -26
  62. data/examples/http/http_server.rb +10 -10
  63. data/examples/http/http_server_forked.rb +6 -5
  64. data/examples/http/http_server_throttled.rb +3 -3
  65. data/examples/http/http_ws_server.rb +11 -11
  66. data/examples/http/https_raw_client.rb +1 -1
  67. data/examples/http/https_server.rb +8 -8
  68. data/examples/http/https_wss_server.rb +13 -11
  69. data/examples/http/rack_server.rb +2 -2
  70. data/examples/http/rack_server_https.rb +4 -4
  71. data/examples/http/rack_server_https_forked.rb +5 -5
  72. data/examples/http/websocket_secure_server.rb +6 -6
  73. data/examples/http/websocket_server.rb +5 -5
  74. data/examples/interfaces/pg_client.rb +4 -4
  75. data/examples/interfaces/pg_pool.rb +13 -6
  76. data/examples/interfaces/pg_transaction.rb +5 -4
  77. data/examples/interfaces/redis_channels.rb +15 -11
  78. data/examples/interfaces/redis_client.rb +2 -2
  79. data/examples/interfaces/redis_pubsub.rb +2 -1
  80. data/examples/interfaces/redis_pubsub_perf.rb +13 -9
  81. data/examples/io/backticks.rb +11 -0
  82. data/examples/io/cat.rb +4 -5
  83. data/examples/io/echo_client.rb +9 -4
  84. data/examples/io/echo_client_from_stdin.rb +20 -0
  85. data/examples/io/echo_pipe.rb +7 -8
  86. data/examples/io/echo_server.rb +8 -6
  87. data/examples/io/echo_server_with_timeout.rb +13 -10
  88. data/examples/io/echo_stdin.rb +3 -3
  89. data/examples/io/httparty.rb +2 -2
  90. data/examples/io/httparty_multi.rb +8 -4
  91. data/examples/io/httparty_threaded.rb +6 -2
  92. data/examples/io/io_read.rb +2 -2
  93. data/examples/io/irb.rb +16 -4
  94. data/examples/io/net-http.rb +3 -3
  95. data/examples/io/open.rb +17 -0
  96. data/examples/io/system.rb +3 -3
  97. data/examples/io/tcpserver.rb +15 -0
  98. data/examples/io/tcpsocket.rb +6 -5
  99. data/examples/performance/multi_snooze.rb +29 -0
  100. data/examples/performance/{perf_snooze.rb → snooze.rb} +7 -5
  101. data/examples/performance/snooze_raw.rb +39 -0
  102. data/ext/gyro/async.c +165 -0
  103. data/ext/gyro/child.c +167 -0
  104. data/ext/{ev → gyro}/extconf.rb +4 -3
  105. data/ext/gyro/gyro.c +316 -0
  106. data/ext/{ev/ev.h → gyro/gyro.h} +12 -7
  107. data/ext/gyro/gyro_ext.c +23 -0
  108. data/ext/{ev → gyro}/io.c +65 -57
  109. data/ext/{ev → gyro}/libev.h +0 -0
  110. data/ext/gyro/signal.c +117 -0
  111. data/ext/{ev → gyro}/socket.c +61 -6
  112. data/ext/gyro/timer.c +199 -0
  113. data/ext/libev/Changes +35 -0
  114. data/ext/libev/README +2 -1
  115. data/ext/libev/ev.c +213 -151
  116. data/ext/libev/ev.h +95 -88
  117. data/ext/libev/ev_epoll.c +26 -15
  118. data/ext/libev/ev_kqueue.c +11 -5
  119. data/ext/libev/ev_linuxaio.c +642 -0
  120. data/ext/libev/ev_poll.c +13 -8
  121. data/ext/libev/ev_port.c +5 -2
  122. data/ext/libev/ev_vars.h +14 -3
  123. data/ext/libev/ev_wrap.h +16 -0
  124. data/lib/ev_ext.bundle +0 -0
  125. data/lib/polyphony.rb +46 -50
  126. data/lib/polyphony/auto_run.rb +12 -0
  127. data/lib/polyphony/core/cancel_scope.rb +11 -7
  128. data/lib/polyphony/core/channel.rb +16 -9
  129. data/lib/polyphony/core/coprocess.rb +101 -51
  130. data/lib/polyphony/core/exceptions.rb +14 -12
  131. data/lib/polyphony/core/resource_pool.rb +21 -8
  132. data/lib/polyphony/core/supervisor.rb +10 -5
  133. data/lib/polyphony/core/sync.rb +7 -6
  134. data/lib/polyphony/core/thread.rb +4 -4
  135. data/lib/polyphony/core/thread_pool.rb +4 -4
  136. data/lib/polyphony/core/throttler.rb +6 -4
  137. data/lib/polyphony/extensions/core.rb +253 -0
  138. data/lib/polyphony/extensions/io.rb +28 -16
  139. data/lib/polyphony/extensions/openssl.rb +2 -1
  140. data/lib/polyphony/extensions/socket.rb +47 -52
  141. data/lib/polyphony/http.rb +4 -3
  142. data/lib/polyphony/http/agent.rb +68 -57
  143. data/lib/polyphony/http/server.rb +5 -5
  144. data/lib/polyphony/http/server/http1.rb +268 -0
  145. data/lib/polyphony/http/server/http2.rb +62 -0
  146. data/lib/polyphony/http/server/http2_stream.rb +104 -0
  147. data/lib/polyphony/http/server/rack.rb +64 -0
  148. data/lib/polyphony/http/server/request.rb +119 -0
  149. data/lib/polyphony/net.rb +26 -15
  150. data/lib/polyphony/postgres.rb +17 -13
  151. data/lib/polyphony/redis.rb +16 -15
  152. data/lib/polyphony/version.rb +1 -1
  153. data/lib/polyphony/websocket.rb +11 -4
  154. data/polyphony.gemspec +13 -9
  155. data/test/eg.rb +27 -0
  156. data/test/helper.rb +25 -0
  157. data/test/run.rb +5 -0
  158. data/test/test_async.rb +33 -0
  159. data/test/test_coprocess.rb +239 -77
  160. data/test/test_core.rb +95 -61
  161. data/test/test_gyro.rb +148 -0
  162. data/test/test_http_server.rb +313 -0
  163. data/test/test_io.rb +79 -27
  164. data/test/test_kernel.rb +22 -12
  165. data/test/test_signal.rb +36 -0
  166. data/test/test_timer.rb +24 -0
  167. metadata +89 -33
  168. data/examples/core/nested_async.rb +0 -17
  169. data/examples/core/next_tick.rb +0 -12
  170. data/examples/core/sleep_spawn.rb +0 -19
  171. data/examples/core/spawn.rb +0 -14
  172. data/examples/core/spawn_error.rb +0 -28
  173. data/examples/performance/perf_multi_snooze.rb +0 -21
  174. data/ext/ev/async.c +0 -168
  175. data/ext/ev/child.c +0 -169
  176. data/ext/ev/ev_ext.c +0 -23
  177. data/ext/ev/ev_module.c +0 -242
  178. data/ext/ev/signal.c +0 -119
  179. data/ext/ev/timer.c +0 -197
  180. data/lib/polyphony/core/fiber_pool.rb +0 -98
  181. data/lib/polyphony/extensions/kernel.rb +0 -169
  182. data/lib/polyphony/http/http1_adapter.rb +0 -254
  183. data/lib/polyphony/http/http2_adapter.rb +0 -157
  184. data/lib/polyphony/http/rack.rb +0 -25
  185. data/lib/polyphony/http/request.rb +0 -66
  186. 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
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- next_tick do
7
- puts "two"
8
- next_tick { puts "four" }
9
- puts "three"
10
- end
11
-
12
- puts "one"
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- spin {
7
- 10.times { |i|
8
- sleep 0.1;
9
- p i
10
- }
11
- }
12
-
13
- spin {
14
- puts "going to sleep..."
15
- sleep 1
16
- puts "woke up"
17
- }.await
18
-
19
- puts "done"
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def my_sleep(t)
7
- puts "going to sleep..."
8
- sleep t
9
- puts "woke up"
10
- end
11
-
12
- spin do
13
- async { my_sleep(1) }.await
14
- end
@@ -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
- }