polyphony 0.38 → 0.43

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +11 -2
  3. data/.gitignore +2 -2
  4. data/.rubocop.yml +30 -0
  5. data/CHANGELOG.md +25 -2
  6. data/Gemfile.lock +15 -12
  7. data/README.md +2 -1
  8. data/Rakefile +3 -3
  9. data/TODO.md +27 -97
  10. data/docs/_config.yml +56 -7
  11. data/docs/_sass/custom/custom.scss +0 -30
  12. data/docs/_sass/overrides.scss +0 -46
  13. data/docs/{user-guide → _user-guide}/all-about-timers.md +0 -0
  14. data/docs/_user-guide/index.md +9 -0
  15. data/docs/{user-guide → _user-guide}/web-server.md +0 -0
  16. data/docs/api-reference/fiber.md +2 -2
  17. data/docs/api-reference/index.md +9 -0
  18. data/docs/api-reference/polyphony-process.md +1 -1
  19. data/docs/api-reference/thread.md +1 -1
  20. data/docs/faq.md +21 -11
  21. data/docs/getting-started/index.md +10 -0
  22. data/docs/getting-started/installing.md +2 -6
  23. data/docs/getting-started/overview.md +486 -0
  24. data/docs/getting-started/tutorial.md +27 -19
  25. data/docs/index.md +1 -1
  26. data/docs/main-concepts/concurrency.md +0 -5
  27. data/docs/main-concepts/design-principles.md +69 -21
  28. data/docs/main-concepts/extending.md +1 -1
  29. data/docs/main-concepts/index.md +9 -0
  30. data/examples/core/01-spinning-up-fibers.rb +1 -0
  31. data/examples/core/03-interrupting.rb +4 -1
  32. data/examples/core/04-handling-signals.rb +19 -0
  33. data/examples/core/xx-agent.rb +102 -0
  34. data/examples/core/xx-sleeping.rb +14 -6
  35. data/examples/io/tunnel.rb +48 -0
  36. data/examples/io/xx-irb.rb +1 -1
  37. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
  38. data/examples/performance/thread-vs-fiber/polyphony_server.rb +13 -36
  39. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  40. data/examples/performance/xx-array.rb +11 -0
  41. data/examples/performance/xx-fiber-switch.rb +9 -0
  42. data/examples/performance/xx-snooze.rb +15 -0
  43. data/ext/{gyro → polyphony}/extconf.rb +2 -2
  44. data/ext/{gyro → polyphony}/fiber.c +17 -23
  45. data/ext/{gyro → polyphony}/libev.c +0 -0
  46. data/ext/{gyro → polyphony}/libev.h +0 -0
  47. data/ext/polyphony/libev_agent.c +718 -0
  48. data/ext/polyphony/libev_queue.c +216 -0
  49. data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -40
  50. data/ext/{gyro/gyro.h → polyphony/polyphony.h} +19 -39
  51. data/ext/polyphony/polyphony_ext.c +23 -0
  52. data/ext/{gyro → polyphony}/socket.c +21 -18
  53. data/ext/polyphony/thread.c +206 -0
  54. data/ext/{gyro → polyphony}/tracing.c +1 -1
  55. data/lib/polyphony.rb +19 -14
  56. data/lib/polyphony/adapters/irb.rb +1 -1
  57. data/lib/polyphony/adapters/postgres.rb +6 -5
  58. data/lib/polyphony/adapters/process.rb +5 -5
  59. data/lib/polyphony/adapters/trace.rb +28 -28
  60. data/lib/polyphony/core/channel.rb +3 -3
  61. data/lib/polyphony/core/exceptions.rb +1 -1
  62. data/lib/polyphony/core/global_api.rb +13 -11
  63. data/lib/polyphony/core/resource_pool.rb +3 -3
  64. data/lib/polyphony/core/sync.rb +2 -2
  65. data/lib/polyphony/core/thread_pool.rb +6 -6
  66. data/lib/polyphony/core/throttler.rb +13 -6
  67. data/lib/polyphony/event.rb +27 -0
  68. data/lib/polyphony/extensions/core.rb +22 -14
  69. data/lib/polyphony/extensions/fiber.rb +4 -4
  70. data/lib/polyphony/extensions/io.rb +59 -25
  71. data/lib/polyphony/extensions/openssl.rb +36 -16
  72. data/lib/polyphony/extensions/socket.rb +27 -9
  73. data/lib/polyphony/extensions/thread.rb +16 -9
  74. data/lib/polyphony/net.rb +9 -9
  75. data/lib/polyphony/version.rb +1 -1
  76. data/polyphony.gemspec +4 -4
  77. data/test/helper.rb +14 -1
  78. data/test/test_agent.rb +124 -0
  79. data/test/{test_async.rb → test_event.rb} +15 -7
  80. data/test/test_ext.rb +25 -4
  81. data/test/test_fiber.rb +19 -10
  82. data/test/test_global_api.rb +4 -4
  83. data/test/test_io.rb +46 -24
  84. data/test/test_queue.rb +74 -0
  85. data/test/test_signal.rb +3 -40
  86. data/test/test_socket.rb +34 -0
  87. data/test/test_thread.rb +37 -16
  88. data/test/test_trace.rb +6 -5
  89. metadata +40 -43
  90. data/docs/_includes/nav.html +0 -51
  91. data/docs/_includes/prevnext.html +0 -17
  92. data/docs/_layouts/default.html +0 -106
  93. data/docs/api-reference.md +0 -11
  94. data/docs/api-reference/gyro-async.md +0 -57
  95. data/docs/api-reference/gyro-child.md +0 -29
  96. data/docs/api-reference/gyro-queue.md +0 -44
  97. data/docs/api-reference/gyro-timer.md +0 -51
  98. data/docs/api-reference/gyro.md +0 -25
  99. data/docs/getting-started.md +0 -10
  100. data/docs/main-concepts.md +0 -10
  101. data/docs/user-guide.md +0 -10
  102. data/examples/core/forever_sleep.rb +0 -19
  103. data/ext/gyro/async.c +0 -162
  104. data/ext/gyro/child.c +0 -141
  105. data/ext/gyro/gyro_ext.c +0 -33
  106. data/ext/gyro/io.c +0 -489
  107. data/ext/gyro/queue.c +0 -142
  108. data/ext/gyro/selector.c +0 -228
  109. data/ext/gyro/signal.c +0 -133
  110. data/ext/gyro/thread.c +0 -308
  111. data/ext/gyro/timer.c +0 -149
  112. data/test/test_timer.rb +0 -56
@@ -1,308 +0,0 @@
1
- #include "gyro.h"
2
-
3
- static VALUE cQueue;
4
-
5
- static ID ID_create_event_selector;
6
- static ID ID_deactivate_all_watchers_post_fork;
7
- static ID ID_empty;
8
- static ID ID_fiber_ref_count;
9
- static ID ID_ivar_event_selector_proc;
10
- static ID ID_ivar_event_selector;
11
- static ID ID_ivar_join_wait_queue;
12
- static ID ID_ivar_main_fiber;
13
- static ID ID_ivar_result;
14
- static ID ID_ivar_terminated;
15
- static ID ID_pop;
16
- static ID ID_push;
17
- static ID ID_run_queue;
18
- static ID ID_runnable_next;
19
- static ID ID_stop;
20
-
21
- VALUE event_selector_factory_proc(RB_BLOCK_CALL_FUNC_ARGLIST(args, klass)) {
22
- return rb_funcall(klass, ID_new, 1, rb_ary_entry(args, 0));
23
- }
24
-
25
- static VALUE Thread_event_selector_set_proc(VALUE self, VALUE proc) {
26
- if (!rb_obj_is_proc(proc)) {
27
- proc = rb_proc_new(event_selector_factory_proc, proc);
28
- }
29
- rb_ivar_set(self, ID_ivar_event_selector_proc, proc);
30
- return self;
31
- }
32
-
33
- static VALUE Thread_create_event_selector(VALUE self, VALUE thread) {
34
- VALUE selector_proc = rb_ivar_get(self, ID_ivar_event_selector_proc);
35
- if (selector_proc == Qnil) {
36
- rb_raise(rb_eRuntimeError, "No event_selector_proc defined");
37
- }
38
-
39
- return rb_funcall(selector_proc, ID_call, 1, thread);
40
- }
41
-
42
- static VALUE Thread_setup_fiber_scheduling(VALUE self) {
43
- rb_ivar_set(self, ID_ivar_main_fiber, rb_fiber_current());
44
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(0));
45
- VALUE queue = rb_ary_new();
46
- rb_ivar_set(self, ID_run_queue, queue);
47
- VALUE selector = rb_funcall(rb_cThread, ID_create_event_selector, 1, self);
48
- rb_ivar_set(self, ID_ivar_event_selector, selector);
49
-
50
- return self;
51
- }
52
-
53
- static VALUE Thread_stop_event_selector(VALUE self) {
54
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
55
- if (selector != Qnil) {
56
- rb_funcall(selector, ID_stop, 0);
57
- }
58
- // Nullify the selector in order to prevent running the
59
- // selector after the thread is done running.
60
- rb_ivar_set(self, ID_ivar_event_selector, Qnil);
61
-
62
- return self;
63
- }
64
-
65
- static VALUE Thread_deactivate_all_watchers_post_fork(VALUE self) {
66
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
67
- if (selector != Qnil) {
68
- rb_funcall(selector, ID_deactivate_all_watchers_post_fork, 0);
69
- }
70
-
71
- return self;
72
- }
73
-
74
- VALUE Thread_ref(VALUE self) {
75
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
76
- int new_count = NUM2INT(count) + 1;
77
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(new_count));
78
- return self;
79
- }
80
-
81
- VALUE Thread_unref(VALUE self) {
82
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
83
- int new_count = NUM2INT(count) - 1;
84
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(new_count));
85
- return self;
86
- }
87
-
88
- int Thread_fiber_ref_count(VALUE self) {
89
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
90
- return NUM2INT(count);
91
- }
92
-
93
- void Thread_fiber_reset_ref_count(VALUE self) {
94
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(0));
95
- }
96
-
97
- static VALUE SYM_scheduled_fibers;
98
- static VALUE SYM_pending_watchers;
99
-
100
- static VALUE Thread_fiber_scheduling_stats(VALUE self) {
101
- VALUE stats = rb_hash_new();
102
- VALUE queue = rb_ivar_get(self, ID_run_queue);
103
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
104
-
105
- long scheduled_count = RARRAY_LEN(queue);
106
- rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
107
-
108
- long pending_count = Gyro_Selector_pending_count(selector);
109
- rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
110
-
111
- return stats;
112
- }
113
-
114
- VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
115
- if (rb_fiber_alive_p(fiber) != Qtrue) {
116
- return self;
117
- }
118
-
119
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
120
- // if fiber is already scheduled, just set the scheduled value, then return
121
- rb_ivar_set(fiber, ID_runnable_value, value);
122
- if (rb_ivar_get(fiber, ID_runnable) != Qnil) {
123
- return self;
124
- }
125
-
126
- VALUE queue = rb_ivar_get(self, ID_run_queue);
127
- rb_ary_push(queue, fiber);
128
- rb_ivar_set(fiber, ID_runnable, Qtrue);
129
-
130
- if (rb_thread_current() != self) {
131
- // if the fiber scheduling is done across threads, we need to make sure the
132
- // target thread is woken up in case it is in the middle of running its
133
- // event selector. Otherwise it's gonna be stuck waiting for an event to
134
- // happen, not knowing that it there's already a fiber ready to run in its
135
- // run queue.
136
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
137
- if (selector != Qnil) {
138
- Gyro_Selector_break_out_of_ev_loop(selector);
139
- }
140
- }
141
- return self;
142
- }
143
-
144
- VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value) {
145
- if (rb_fiber_alive_p(fiber) != Qtrue) {
146
- return self;
147
- }
148
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
149
- rb_ivar_set(fiber, ID_runnable_value, value);
150
-
151
- VALUE queue = rb_ivar_get(self, ID_run_queue);
152
-
153
- // if fiber is already scheduled, remove it from the run queue
154
- if (rb_ivar_get(fiber, ID_runnable) != Qnil) {
155
- rb_ary_delete(queue, fiber);
156
- } else {
157
- rb_ivar_set(fiber, ID_runnable, Qtrue);
158
- }
159
-
160
- // the fiber is given priority by putting it at the front of the run queue
161
- rb_ary_unshift(queue, fiber);
162
-
163
- if (rb_thread_current() != self) {
164
- // if the fiber scheduling is done across threads, we need to make sure the
165
- // target thread is woken up in case it is in the middle of running its
166
- // event selector. Otherwise it's gonna be stuck waiting for an event to
167
- // happen, not knowing that it there's already a fiber ready to run in its
168
- // run queue.
169
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
170
- if (selector != Qnil) {
171
- Gyro_Selector_break_out_of_ev_loop(selector);
172
- }
173
- }
174
- return self;
175
- }
176
-
177
- VALUE Thread_switch_fiber(VALUE self) {
178
- VALUE current_fiber = rb_fiber_current();
179
- if (__tracing_enabled__) {
180
- if (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse) {
181
- rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_switchpoint, current_fiber);
182
- }
183
- }
184
- VALUE queue = rb_ivar_get(self, ID_run_queue);
185
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
186
-
187
- VALUE next_fiber;
188
-
189
- while (1) {
190
- next_fiber = rb_ary_shift(queue);
191
- // if (break_flag != 0) {
192
- // return Qnil;
193
- // }
194
- int ref_count = Thread_fiber_ref_count(self);
195
- if (next_fiber != Qnil) {
196
- if (ref_count > 0) {
197
- // this mechanism prevents event starvation in case the run queue never
198
- // empties
199
- Gyro_Selector_run_no_wait(selector, current_fiber, RARRAY_LEN(queue));
200
- }
201
- break;
202
- }
203
- if (ref_count == 0) {
204
- break;
205
- }
206
-
207
- Gyro_Selector_run(selector, current_fiber);
208
- }
209
-
210
- if (next_fiber == Qnil) {
211
- return Qnil;
212
- }
213
-
214
- // run next fiber
215
- VALUE value = rb_ivar_get(next_fiber, ID_runnable_value);
216
- FIBER_TRACE(3, SYM_fiber_run, next_fiber, value);
217
-
218
- rb_ivar_set(next_fiber, ID_runnable, Qnil);
219
- RB_GC_GUARD(next_fiber);
220
- RB_GC_GUARD(value);
221
- return rb_funcall(next_fiber, ID_transfer, 1, value);
222
- }
223
-
224
- VALUE Thread_reset_fiber_scheduling(VALUE self) {
225
- VALUE queue = rb_ivar_get(self, ID_run_queue);
226
- rb_ary_clear(queue);
227
- Thread_fiber_reset_ref_count(self);
228
- return self;
229
- }
230
-
231
- VALUE Thread_post_fork(VALUE self) {
232
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
233
- Gyro_Selector_post_fork(selector);
234
-
235
- return self;
236
- }
237
-
238
- VALUE Gyro_switchpoint() {
239
- VALUE thread = rb_thread_current();
240
- Thread_ref(thread);
241
- VALUE ret = Thread_switch_fiber(thread);
242
- Thread_unref(thread);
243
- RB_GC_GUARD(ret);
244
- return ret;
245
- }
246
-
247
- VALUE Thread_current_event_selector() {
248
- return rb_ivar_get(rb_thread_current(), ID_ivar_event_selector);
249
- }
250
-
251
- VALUE Thread_fiber_break_out_of_ev_loop(VALUE self, VALUE fiber, VALUE resume_obj) {
252
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
253
- if (fiber != Qnil) {
254
- Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
255
- }
256
-
257
- if (Gyro_Selector_break_out_of_ev_loop(selector) == Qnil) {
258
- // we're not inside the ev_loop, so we just do a switchpoint
259
- Thread_switch_fiber(self);
260
- }
261
-
262
- return self;
263
- }
264
-
265
- void Init_Thread() {
266
- cQueue = rb_const_get(rb_cObject, rb_intern("Queue"));
267
-
268
- rb_define_singleton_method(rb_cThread, "event_selector=", Thread_event_selector_set_proc, 1);
269
- rb_define_singleton_method(rb_cThread, "create_event_selector", Thread_create_event_selector, 1);
270
-
271
- rb_define_method(rb_cThread, "fiber_ref", Thread_ref, 0);
272
- rb_define_method(rb_cThread, "fiber_unref", Thread_unref, 0);
273
-
274
- rb_define_method(rb_cThread, "post_fork", Thread_post_fork, 0);
275
-
276
- rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
277
- rb_define_method(rb_cThread, "stop_event_selector", Thread_stop_event_selector, 0);
278
- rb_define_method(rb_cThread, "deactivate_all_watchers_post_fork", Thread_deactivate_all_watchers_post_fork, 0);
279
- rb_define_method(rb_cThread, "reset_fiber_scheduling", Thread_reset_fiber_scheduling, 0);
280
- rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
281
- rb_define_method(rb_cThread, "break_out_of_ev_loop", Thread_fiber_break_out_of_ev_loop, 2);
282
-
283
- rb_define_method(rb_cThread, "schedule_fiber", Thread_schedule_fiber, 2);
284
- rb_define_method(rb_cThread, "schedule_fiber_with_priority",
285
- Thread_schedule_fiber_with_priority, 2);
286
- rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
287
-
288
- ID_create_event_selector = rb_intern("create_event_selector");
289
- ID_deactivate_all_watchers_post_fork = rb_intern("deactivate_all_watchers_post_fork");
290
- ID_empty = rb_intern("empty?");
291
- ID_fiber_ref_count = rb_intern("fiber_ref_count");
292
- ID_ivar_event_selector = rb_intern("@event_selector");
293
- ID_ivar_event_selector_proc = rb_intern("@event_selector_proc");
294
- ID_ivar_join_wait_queue = rb_intern("@join_wait_queue");
295
- ID_ivar_main_fiber = rb_intern("@main_fiber");
296
- ID_ivar_result = rb_intern("@result");
297
- ID_ivar_terminated = rb_intern("@terminated");
298
- ID_pop = rb_intern("pop");
299
- ID_push = rb_intern("push");
300
- ID_run_queue = rb_intern("run_queue");
301
- ID_runnable_next = rb_intern("runnable_next");
302
- ID_stop = rb_intern("stop");
303
-
304
- SYM_scheduled_fibers = ID2SYM(rb_intern("scheduled_fibers"));
305
- SYM_pending_watchers = ID2SYM(rb_intern("pending_watchers"));
306
- rb_global_variable(&SYM_scheduled_fibers);
307
- rb_global_variable(&SYM_pending_watchers);
308
- }
@@ -1,149 +0,0 @@
1
- #include "gyro.h"
2
-
3
- struct Gyro_Timer {
4
- struct ev_timer ev_timer;
5
- struct ev_loop *ev_loop;
6
- int active;
7
- double after;
8
- double repeat;
9
- VALUE self;
10
- VALUE fiber;
11
- VALUE selector;
12
- };
13
-
14
- VALUE cGyro_Timer = Qnil;
15
-
16
- static void Gyro_Timer_mark(void *ptr) {
17
- struct Gyro_Timer *timer = ptr;
18
- if (timer->fiber != Qnil) {
19
- rb_gc_mark(timer->fiber);
20
- }
21
- if (timer->selector != Qnil) {
22
- rb_gc_mark(timer->selector);
23
- }
24
- }
25
-
26
- static void Gyro_Timer_free(void *ptr) {
27
- struct Gyro_Timer *timer = ptr;
28
- switch (timer->active) {
29
- case GYRO_WATCHER_POST_FORK:
30
- return;
31
- case 1:
32
- ev_clear_pending(timer->ev_loop, &timer->ev_timer);
33
- ev_timer_stop(timer->ev_loop, &timer->ev_timer);
34
- default:
35
- xfree(timer);
36
- }
37
- }
38
-
39
- static size_t Gyro_Timer_size(const void *ptr) {
40
- return sizeof(struct Gyro_Timer);
41
- }
42
-
43
- static const rb_data_type_t Gyro_Timer_type = {
44
- "Gyro_Timer",
45
- {Gyro_Timer_mark, Gyro_Timer_free, Gyro_Timer_size,},
46
- 0, 0, 0
47
- };
48
-
49
- static VALUE Gyro_Timer_allocate(VALUE klass) {
50
- struct Gyro_Timer *timer = ALLOC(struct Gyro_Timer);
51
- return TypedData_Wrap_Struct(klass, &Gyro_Timer_type, timer);
52
- }
53
-
54
- #define GetGyro_Timer(obj, timer) \
55
- TypedData_Get_Struct((obj), struct Gyro_Timer, &Gyro_Timer_type, (timer))
56
-
57
- inline void timer_activate(struct Gyro_Timer *timer) {
58
- timer->fiber = rb_fiber_current();
59
- timer->selector = Thread_current_event_selector();
60
- timer->ev_loop = Gyro_Selector_ev_loop(timer->selector);
61
-
62
- if (timer->active) return;
63
-
64
- timer->active = 1;
65
- Gyro_Selector_add_active_watcher(timer->selector, timer->self);
66
- ev_timer_start(timer->ev_loop, &timer->ev_timer);
67
- }
68
-
69
- inline void timer_deactivate(struct Gyro_Timer *timer, int non_recurring_only) {
70
- if (!timer->active) return;
71
-
72
- if (!timer->repeat || !non_recurring_only) {
73
- ev_timer_stop(timer->ev_loop, &timer->ev_timer);
74
- if (RTEST(timer->selector)) {
75
- Gyro_Selector_remove_active_watcher(timer->selector, timer->self);
76
- timer->selector = Qnil;
77
- }
78
- timer->ev_loop = 0;
79
- timer->active = 0;
80
- }
81
-
82
- timer->fiber = Qnil;
83
- }
84
-
85
- void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
86
- struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
87
-
88
- Fiber_make_runnable(timer->fiber, DBL2NUM(timer->after));
89
- timer_deactivate(timer, 1);
90
- }
91
-
92
- static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
93
- struct Gyro_Timer *timer;
94
-
95
- GetGyro_Timer(self, timer);
96
-
97
- timer->self = self;
98
- timer->fiber = Qnil;
99
- timer->selector = Qnil;
100
- timer->after = NUM2DBL(after);
101
- timer->repeat = NUM2DBL(repeat);
102
- timer->active = 0;
103
- timer->ev_loop = 0;
104
-
105
- ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
106
-
107
- return Qnil;
108
- }
109
-
110
- VALUE Gyro_Timer_stop(VALUE self) {
111
- struct Gyro_Timer *timer;
112
- GetGyro_Timer(self, timer);
113
-
114
- timer_deactivate(timer, 0);
115
- return self;
116
- }
117
-
118
- VALUE Gyro_Timer_await(VALUE self) {
119
- struct Gyro_Timer *timer;
120
- GetGyro_Timer(self, timer);
121
-
122
- timer_activate(timer);
123
- VALUE ret = Gyro_switchpoint();
124
- timer_deactivate(timer, 1);
125
-
126
- TEST_RESUME_EXCEPTION(ret);
127
- RB_GC_GUARD(ret);
128
- return ret;
129
- }
130
-
131
- VALUE Gyro_Timer_deactivate_post_fork(VALUE self) {
132
- struct Gyro_Timer *timer;
133
- GetGyro_Timer(self, timer);
134
-
135
- if (timer->active)
136
- timer->active = GYRO_WATCHER_POST_FORK;
137
-
138
- return self;
139
- }
140
-
141
- void Init_Gyro_Timer() {
142
- cGyro_Timer = rb_define_class_under(mGyro, "Timer", rb_cData);
143
- rb_define_alloc_func(cGyro_Timer, Gyro_Timer_allocate);
144
-
145
- rb_define_method(cGyro_Timer, "initialize", Gyro_Timer_initialize, 2);
146
- rb_define_method(cGyro_Timer, "await", Gyro_Timer_await, 0);
147
- rb_define_method(cGyro_Timer, "deactivate_post_fork", Gyro_Timer_deactivate_post_fork, 0);
148
- rb_define_method(cGyro_Timer, "stop", Gyro_Timer_stop, 0);
149
- }