polyphony 0.19 → 0.20

Sign up to get free protection for your applications and to get access to all the features.
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
data/ext/ev/ev_ext.c DELETED
@@ -1,23 +0,0 @@
1
- #include "ev.h"
2
- #include "../libev/ev.c"
3
-
4
- void Init_EV();
5
- void Init_EV_Async();
6
- void Init_EV_Child();
7
- void Init_EV_IO();
8
- void Init_EV_Signal();
9
- void Init_EV_Timer();
10
- void Init_Socket();
11
-
12
- void Init_ev_ext() {
13
- ev_set_allocator(xrealloc);
14
-
15
- Init_EV();
16
- Init_EV_Async();
17
- Init_EV_Child();
18
- Init_EV_IO();
19
- Init_EV_Signal();
20
- Init_EV_Timer();
21
-
22
- Init_Socket();
23
- }
data/ext/ev/ev_module.c DELETED
@@ -1,242 +0,0 @@
1
- #include "ev.h"
2
-
3
- static VALUE mEV = Qnil;
4
-
5
- static VALUE EV_run(VALUE self);
6
- static VALUE EV_break(VALUE self);
7
- static VALUE EV_restart(VALUE self);
8
- static VALUE EV_rerun(VALUE self);
9
-
10
- static VALUE EV_ref(VALUE self);
11
- static VALUE EV_unref(VALUE self);
12
-
13
- static VALUE EV_next_tick(VALUE self);
14
- static VALUE EV_snooze(VALUE self);
15
- static VALUE EV_post_fork(VALUE self);
16
-
17
- static VALUE EV_suspend(VALUE self);
18
- static VALUE EV_schedule_fiber(VALUE self, VALUE fiber, VALUE value);
19
-
20
- static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self);
21
-
22
- static VALUE watcher_refs;
23
- static VALUE next_tick_items;
24
-
25
- static struct ev_idle next_tick_watcher;
26
- static int next_tick_active;
27
- void EV_next_tick_callback(ev_loop *ev_loop, struct ev_idle *watcher, int revents);
28
-
29
- VALUE EV_reactor_fiber;
30
- VALUE EV_root_fiber;
31
-
32
- ID ID_call;
33
- ID ID_caller;
34
- ID ID_clear;
35
- ID ID_each;
36
- ID ID_inspect;
37
- ID ID_raise;
38
- ID ID_read_watcher;
39
- ID ID_scheduled_value;
40
- ID ID_transfer;
41
- ID ID_write_watcher;
42
- ID ID_R;
43
- ID ID_W;
44
- ID ID_RW;
45
-
46
- void Init_EV() {
47
- mEV = rb_define_module("EV");
48
-
49
- rb_define_singleton_method(mEV, "break", EV_break, 0);
50
- rb_define_singleton_method(mEV, "restart", EV_restart, 0);
51
- rb_define_singleton_method(mEV, "rerun", EV_rerun, 0);
52
- rb_define_singleton_method(mEV, "ref", EV_ref, 0);
53
- rb_define_singleton_method(mEV, "unref", EV_unref, 0);
54
- rb_define_singleton_method(mEV, "next_tick", EV_next_tick, 0);
55
- rb_define_singleton_method(mEV, "snooze", EV_snooze, 0);
56
- rb_define_singleton_method(mEV, "post_fork", EV_post_fork, 0);
57
- rb_define_singleton_method(mEV, "schedule_fiber", EV_schedule_fiber, 2);
58
-
59
- rb_define_global_function("suspend", EV_suspend, 0);
60
- rb_define_global_function("snooze", EV_snooze, 0);
61
- rb_define_global_function("next_tick", EV_next_tick, 0);
62
-
63
- VALUE cFiber = rb_const_get(rb_cObject, rb_intern("Fiber"));
64
- rb_define_method(cFiber, "safe_transfer", Fiber_safe_transfer, -1);
65
-
66
- ID_call = rb_intern("call");
67
- ID_caller = rb_intern("caller");
68
- ID_clear = rb_intern("clear");
69
- ID_each = rb_intern("each");
70
- ID_inspect = rb_intern("inspect");
71
- ID_raise = rb_intern("raise");
72
- ID_read_watcher = rb_intern("read_watcher");
73
- ID_scheduled_value = rb_intern("@scheduled_value");
74
- ID_transfer = rb_intern("transfer");
75
- ID_write_watcher = rb_intern("write_watcher");
76
- ID_R = rb_intern("r");
77
- ID_W = rb_intern("w");
78
- ID_RW = rb_intern("rw");
79
-
80
- EV_root_fiber = rb_fiber_current();
81
- EV_reactor_fiber = rb_fiber_new(EV_run, Qnil);
82
- rb_gv_set("__reactor_fiber__", EV_reactor_fiber);
83
-
84
-
85
- watcher_refs = rb_hash_new();
86
- rb_global_variable(&watcher_refs);
87
-
88
- next_tick_items = rb_ary_new();
89
- rb_global_variable(&next_tick_items);
90
-
91
- ev_idle_init(&next_tick_watcher, EV_next_tick_callback);
92
- next_tick_active = 0;
93
- }
94
-
95
- static VALUE EV_run(VALUE self) {
96
- ev_run(EV_DEFAULT, 0);
97
- rb_gv_set("__reactor_fiber__", Qnil);
98
- return Qnil;
99
- }
100
-
101
- static VALUE EV_break(VALUE self) {
102
- // make sure reactor fiber is alive
103
- if (!RTEST(rb_fiber_alive_p(EV_reactor_fiber))) {
104
- return Qnil;
105
- }
106
-
107
- ev_break(EV_DEFAULT, EVBREAK_ALL);
108
- return YIELD_TO_REACTOR();
109
- }
110
-
111
- static VALUE EV_restart(VALUE self) {
112
- EV_reactor_fiber = rb_fiber_new(EV_run, Qnil);
113
- rb_gv_set("__reactor_fiber__", EV_reactor_fiber);
114
- return Qnil;
115
- }
116
-
117
- static VALUE EV_rerun(VALUE self) {
118
- EV_break(self);
119
- EV_restart(self);
120
- return Qnil;
121
- }
122
-
123
- static VALUE EV_ref(VALUE self) {
124
- ev_ref(EV_DEFAULT);
125
- return Qnil;
126
- }
127
-
128
- static VALUE EV_unref(VALUE self) {
129
- ev_unref(EV_DEFAULT);
130
- return Qnil;
131
- }
132
-
133
- void EV_add_watcher_ref(VALUE obj) {
134
- rb_hash_aset(watcher_refs, rb_obj_id(obj), obj);
135
- }
136
-
137
- void EV_del_watcher_ref(VALUE obj) {
138
- rb_hash_delete(watcher_refs, rb_obj_id(obj));
139
- }
140
-
141
- static VALUE EV_next_tick(VALUE self) {
142
- VALUE proc = rb_block_proc();
143
- if (RTEST(proc)) {
144
- rb_ary_push(next_tick_items, proc);
145
- if (!next_tick_active) {
146
- next_tick_active = 1;
147
- ev_idle_start(EV_DEFAULT, &next_tick_watcher);
148
- }
149
- }
150
- return Qnil;
151
- }
152
-
153
- static VALUE EV_snooze(VALUE self) {
154
- VALUE ret;
155
- VALUE fiber = rb_fiber_current();
156
-
157
- rb_ary_push(next_tick_items, fiber);
158
- if (!next_tick_active) {
159
- next_tick_active = 1;
160
- ev_idle_start(EV_DEFAULT, &next_tick_watcher);
161
- }
162
-
163
- ret = YIELD_TO_REACTOR();
164
-
165
- // fiber is resumed, check if resumed value is an exception
166
- if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
167
- rb_ary_delete(next_tick_items, fiber);
168
- return rb_funcall(ret, ID_raise, 1, ret);
169
- }
170
- else {
171
- return ret;
172
- }
173
- }
174
-
175
- static VALUE EV_post_fork(VALUE self) {
176
- ev_loop_fork(EV_DEFAULT);
177
-
178
- EV_reactor_fiber = rb_fiber_new(EV_run, Qnil);
179
- rb_gv_set("__reactor_fiber__", EV_reactor_fiber);
180
- EV_root_fiber = rb_fiber_current();
181
-
182
- return Qnil;
183
- }
184
-
185
- VALUE EV_next_tick_runner(VALUE proc) {
186
- if (rb_obj_is_proc(proc)) {
187
- rb_funcall(proc, ID_call, 1, Qtrue);
188
- }
189
- else {
190
- SCHEDULE_FIBER(proc, 1, rb_ivar_get(proc, ID_scheduled_value));
191
- }
192
- return Qnil;
193
- }
194
-
195
- void EV_next_tick_callback(ev_loop *ev_loop, struct ev_idle *watcher, int revents) {
196
- VALUE scheduled_items = next_tick_items;
197
- next_tick_items = rb_ary_new();
198
-
199
- long len = RARRAY_LEN(scheduled_items);
200
- for (long i = 0; i < len; i++) {
201
- EV_next_tick_runner(RARRAY_AREF(scheduled_items, i));
202
- }
203
-
204
- // if no next tick items were added during callback, stop the idle watcher
205
- if (rb_array_len(next_tick_items) == 0) {
206
- next_tick_active = 0;
207
- ev_idle_stop(EV_DEFAULT, &next_tick_watcher);
208
- }
209
- }
210
-
211
- static VALUE EV_suspend(VALUE self) {
212
- if (!RTEST(rb_fiber_alive_p(EV_reactor_fiber))) {
213
- return Qnil;
214
- }
215
-
216
- VALUE ret = YIELD_TO_REACTOR();
217
-
218
- // fiber is resumed, check if resumed value is an exception
219
- return RTEST(rb_obj_is_kind_of(ret, rb_eException)) ?
220
- rb_funcall(ret, ID_raise, 1, ret) : ret;
221
- }
222
-
223
- static VALUE EV_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
224
- rb_ivar_set(fiber, ID_scheduled_value, value);
225
-
226
- rb_ary_push(next_tick_items, fiber);
227
- if (!next_tick_active) {
228
- next_tick_active = 1;
229
- ev_idle_start(EV_DEFAULT, &next_tick_watcher);
230
- }
231
-
232
- return Qnil;
233
- }
234
-
235
- static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
236
- VALUE arg = (argc == 0) ? Qnil : argv[0];
237
- VALUE ret = rb_funcall(self, ID_transfer, 1, arg);
238
-
239
- // fiber is resumed, check if resumed value is an exception
240
- return RTEST(rb_obj_is_kind_of(ret, rb_eException)) ?
241
- rb_funcall(ret, ID_raise, 1, ret) : ret;
242
- }
data/ext/ev/signal.c DELETED
@@ -1,119 +0,0 @@
1
- #include "ev.h"
2
-
3
- struct EV_Signal {
4
- struct ev_signal ev_signal;
5
- int active;
6
- int signum;
7
- VALUE callback;
8
- };
9
-
10
- static VALUE mEV = Qnil;
11
- static VALUE cEV_Signal = Qnil;
12
-
13
- /* Allocator/deallocator */
14
- static VALUE EV_Signal_allocate(VALUE klass);
15
- static void EV_Signal_mark(void *ptr);
16
- static void EV_Signal_free(void *ptr);
17
- static size_t EV_Signal_size(const void *ptr);
18
-
19
- /* Methods */
20
- static VALUE EV_Signal_initialize(VALUE self, VALUE sig);
21
-
22
- static VALUE EV_Signal_start(VALUE self);
23
- static VALUE EV_Signal_stop(VALUE self);
24
-
25
- void EV_Signal_callback(ev_loop *ev_loop, struct ev_signal *signal, int revents);
26
-
27
- /* Signal encapsulates a signal watcher */
28
- void Init_EV_Signal() {
29
- mEV = rb_define_module("EV");
30
- cEV_Signal = rb_define_class_under(mEV, "Signal", rb_cData);
31
- rb_define_alloc_func(cEV_Signal, EV_Signal_allocate);
32
-
33
- rb_define_method(cEV_Signal, "initialize", EV_Signal_initialize, 1);
34
- rb_define_method(cEV_Signal, "start", EV_Signal_start, 0);
35
- rb_define_method(cEV_Signal, "stop", EV_Signal_stop, 0);
36
- }
37
-
38
- static const rb_data_type_t EV_Signal_type = {
39
- "EV_Signal",
40
- {EV_Signal_mark, EV_Signal_free, EV_Signal_size,},
41
- 0, 0,
42
- RUBY_TYPED_FREE_IMMEDIATELY,
43
- };
44
-
45
- static VALUE EV_Signal_allocate(VALUE klass) {
46
- struct EV_Signal *signal = (struct EV_Signal *)xmalloc(sizeof(struct EV_Signal));
47
- return TypedData_Wrap_Struct(klass, &EV_Signal_type, signal);
48
- }
49
-
50
- static void EV_Signal_mark(void *ptr) {
51
- struct EV_Signal *signal = ptr;
52
- if (signal->callback != Qnil) {
53
- rb_gc_mark(signal->callback);
54
- }
55
- }
56
-
57
- static void EV_Signal_free(void *ptr) {
58
- struct EV_Signal *signal = ptr;
59
- ev_signal_stop(EV_DEFAULT, &signal->ev_signal);
60
- xfree(signal);
61
- }
62
-
63
- static size_t EV_Signal_size(const void *ptr) {
64
- return sizeof(struct EV_Signal);
65
- }
66
-
67
- #define GetEV_Signal(obj, signal) \
68
- TypedData_Get_Struct((obj), struct EV_Signal, &EV_Signal_type, (signal))
69
-
70
- static VALUE EV_Signal_initialize(VALUE self, VALUE sig) {
71
- struct EV_Signal *signal;
72
- VALUE signum = sig;
73
-
74
- GetEV_Signal(self, signal);
75
- signal->signum = NUM2INT(signum);
76
-
77
- if (rb_block_given_p()) {
78
- signal->callback = rb_block_proc();
79
- }
80
-
81
- ev_signal_init(&signal->ev_signal, EV_Signal_callback, signal->signum);
82
-
83
- signal->active = 1;
84
- ev_signal_start(EV_DEFAULT, &signal->ev_signal);
85
-
86
- return Qnil;
87
- }
88
-
89
- void EV_Signal_callback(ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
90
- struct EV_Signal *signal = (struct EV_Signal*)ev_signal;
91
-
92
- if (signal->callback != Qnil) {
93
- rb_funcall(signal->callback, ID_call, 1, INT2NUM(signal->signum));
94
- }
95
- }
96
-
97
- static VALUE EV_Signal_start(VALUE self) {
98
- struct EV_Signal *signal;
99
- GetEV_Signal(self, signal);
100
-
101
- if (!signal->active) {
102
- ev_signal_start(EV_DEFAULT, &signal->ev_signal);
103
- signal->active = 1;
104
- }
105
-
106
- return self;
107
- }
108
-
109
- static VALUE EV_Signal_stop(VALUE self) {
110
- struct EV_Signal *signal;
111
- GetEV_Signal(self, signal);
112
-
113
- if (signal->active) {
114
- ev_signal_stop(EV_DEFAULT, &signal->ev_signal);
115
- signal->active = 0;
116
- }
117
-
118
- return self;
119
- }
data/ext/ev/timer.c DELETED
@@ -1,197 +0,0 @@
1
- #include "ev.h"
2
-
3
- struct EV_Timer {
4
- struct ev_timer ev_timer;
5
- int active;
6
- double after;
7
- double repeat;
8
- VALUE self;
9
- VALUE callback;
10
- VALUE fiber;
11
- };
12
-
13
- static VALUE mEV = Qnil;
14
- static VALUE cEV_Timer = Qnil;
15
-
16
- /* Allocator/deallocator */
17
- static VALUE EV_Timer_allocate(VALUE klass);
18
- static void EV_Timer_mark(void *ptr);
19
- static void EV_Timer_free(void *ptr);
20
- static size_t EV_Timer_size(const void *ptr);
21
-
22
- /* Methods */
23
- static VALUE EV_Timer_initialize(VALUE self, VALUE after, VALUE repeat);
24
-
25
- static VALUE EV_Timer_start(VALUE self);
26
- static VALUE EV_Timer_stop(VALUE self);
27
- static VALUE EV_Timer_reset(VALUE self);
28
- static VALUE EV_Timer_await(VALUE self);
29
-
30
- void EV_Timer_callback(ev_loop *ev_loop, struct ev_timer *timer, int revents);
31
-
32
- /* Timer encapsulates an timer watcher */
33
- void Init_EV_Timer() {
34
- mEV = rb_define_module("EV");
35
- cEV_Timer = rb_define_class_under(mEV, "Timer", rb_cData);
36
- rb_define_alloc_func(cEV_Timer, EV_Timer_allocate);
37
-
38
- rb_define_method(cEV_Timer, "initialize", EV_Timer_initialize, 2);
39
- rb_define_method(cEV_Timer, "start", EV_Timer_start, 0);
40
- rb_define_method(cEV_Timer, "stop", EV_Timer_stop, 0);
41
- rb_define_method(cEV_Timer, "reset", EV_Timer_reset, 0);
42
- rb_define_method(cEV_Timer, "await", EV_Timer_await, 0);
43
- }
44
-
45
- static const rb_data_type_t EV_Timer_type = {
46
- "EV_Timer",
47
- {EV_Timer_mark, EV_Timer_free, EV_Timer_size,},
48
- 0, 0,
49
- RUBY_TYPED_FREE_IMMEDIATELY,
50
- };
51
-
52
- static VALUE EV_Timer_allocate(VALUE klass) {
53
- struct EV_Timer *timer = (struct EV_Timer *)xmalloc(sizeof(struct EV_Timer));
54
- return TypedData_Wrap_Struct(klass, &EV_Timer_type, timer);
55
- }
56
-
57
- static void EV_Timer_mark(void *ptr) {
58
- struct EV_Timer *timer = ptr;
59
- if (timer->callback != Qnil) {
60
- rb_gc_mark(timer->callback);
61
- }
62
- if (timer->fiber != Qnil) {
63
- rb_gc_mark(timer->fiber);
64
- }
65
- }
66
-
67
- static void EV_Timer_free(void *ptr) {
68
- struct EV_Timer *timer = ptr;
69
- if (timer->active) {
70
- ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
71
- }
72
- xfree(timer);
73
- }
74
-
75
- static size_t EV_Timer_size(const void *ptr) {
76
- return sizeof(struct EV_Timer);
77
- }
78
-
79
- #define GetEV_Timer(obj, timer) \
80
- TypedData_Get_Struct((obj), struct EV_Timer, &EV_Timer_type, (timer))
81
-
82
- static VALUE EV_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
83
- struct EV_Timer *timer;
84
-
85
- GetEV_Timer(self, timer);
86
-
87
- timer->self = self;
88
- timer->callback = Qnil;
89
- timer->fiber = Qnil;
90
- timer->after = NUM2DBL(after);
91
- timer->repeat = NUM2DBL(repeat);
92
- timer->active = 0;
93
-
94
- ev_timer_init(&timer->ev_timer, EV_Timer_callback, timer->after, timer->repeat);
95
-
96
- return Qnil;
97
- }
98
-
99
- void EV_Timer_callback(ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
100
- VALUE fiber;
101
- VALUE resume_value;
102
- struct EV_Timer *timer = (struct EV_Timer*)ev_timer;
103
-
104
- if (!timer->repeat) {
105
- timer->active = 0;
106
- EV_del_watcher_ref(timer->self);
107
- }
108
-
109
- if (timer->fiber != Qnil) {
110
- ev_timer_stop(EV_DEFAULT, ev_timer);
111
- EV_del_watcher_ref(timer->self);
112
- timer->active = 0;
113
- fiber = timer->fiber;
114
- timer->fiber = Qnil;
115
- resume_value = DBL2NUM(timer->after);
116
- SCHEDULE_FIBER(fiber, 1, resume_value);
117
- }
118
- else if (timer->callback != Qnil) {
119
- rb_funcall(timer->callback, ID_call, 1, Qtrue);
120
- }
121
- }
122
-
123
- static VALUE EV_Timer_start(VALUE self) {
124
- struct EV_Timer *timer;
125
- GetEV_Timer(self, timer);
126
-
127
- if (rb_block_given_p()) {
128
- timer->callback = rb_block_proc();
129
- }
130
-
131
- if (!timer->active) {
132
- ev_timer_start(EV_DEFAULT, &timer->ev_timer);
133
- timer->active = 1;
134
- EV_add_watcher_ref(self);
135
- }
136
-
137
- return self;
138
- }
139
-
140
- static VALUE EV_Timer_stop(VALUE self) {
141
- struct EV_Timer *timer;
142
- GetEV_Timer(self, timer);
143
-
144
- if (timer->active) {
145
- ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
146
- timer->active = 0;
147
- EV_del_watcher_ref(self);
148
- }
149
-
150
- return self;
151
- }
152
-
153
- static VALUE EV_Timer_reset(VALUE self) {
154
- struct EV_Timer *timer;
155
- int prev_active;
156
- GetEV_Timer(self, timer);
157
-
158
- prev_active = timer->active;
159
-
160
- if (prev_active) {
161
- ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
162
- }
163
- ev_timer_set(&timer->ev_timer, timer->after, timer->repeat);
164
- ev_timer_start(EV_DEFAULT, &timer->ev_timer);
165
- if (!prev_active) {
166
- timer->active = 1;
167
- EV_add_watcher_ref(self);
168
- }
169
-
170
- return self;
171
- }
172
-
173
- static VALUE EV_Timer_await(VALUE self) {
174
- struct EV_Timer *timer;
175
- VALUE ret;
176
-
177
- GetEV_Timer(self, timer);
178
-
179
- timer->fiber = rb_fiber_current();
180
- timer->active = 1;
181
- ev_timer_start(EV_DEFAULT, &timer->ev_timer);
182
- EV_add_watcher_ref(self);
183
-
184
- ret = YIELD_TO_REACTOR();
185
-
186
- // fiber is resumed, check if resumed value is an exception
187
- if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
188
- if (timer->active) {
189
- timer->active = 0;
190
- ev_timer_stop(EV_DEFAULT, &timer->ev_timer);
191
- }
192
- return rb_funcall(ret, ID_raise, 1, ret);
193
- }
194
- else {
195
- return ret;
196
- }
197
- }