polyphony 0.36 → 0.42

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 (118) 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 +28 -2
  6. data/Gemfile +0 -11
  7. data/Gemfile.lock +15 -14
  8. data/README.md +2 -1
  9. data/Rakefile +7 -3
  10. data/TODO.md +28 -95
  11. data/docs/_config.yml +56 -7
  12. data/docs/_sass/custom/custom.scss +0 -30
  13. data/docs/_sass/overrides.scss +0 -46
  14. data/docs/{user-guide → _user-guide}/all-about-timers.md +0 -0
  15. data/docs/_user-guide/index.md +9 -0
  16. data/docs/{user-guide → _user-guide}/web-server.md +0 -0
  17. data/docs/api-reference/fiber.md +2 -2
  18. data/docs/api-reference/index.md +9 -0
  19. data/docs/api-reference/polyphony-process.md +1 -1
  20. data/docs/api-reference/thread.md +1 -1
  21. data/docs/faq.md +21 -11
  22. data/docs/getting-started/index.md +10 -0
  23. data/docs/getting-started/installing.md +2 -6
  24. data/docs/getting-started/overview.md +507 -0
  25. data/docs/getting-started/tutorial.md +27 -19
  26. data/docs/index.md +3 -2
  27. data/docs/main-concepts/concurrency.md +0 -5
  28. data/docs/main-concepts/design-principles.md +69 -21
  29. data/docs/main-concepts/extending.md +1 -1
  30. data/docs/main-concepts/index.md +9 -0
  31. data/examples/core/01-spinning-up-fibers.rb +1 -0
  32. data/examples/core/03-interrupting.rb +4 -1
  33. data/examples/core/04-handling-signals.rb +19 -0
  34. data/examples/core/xx-agent.rb +102 -0
  35. data/examples/core/xx-fork-cleanup.rb +22 -0
  36. data/examples/core/xx-sleeping.rb +14 -6
  37. data/examples/io/tunnel.rb +48 -0
  38. data/examples/io/xx-irb.rb +1 -1
  39. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
  40. data/examples/performance/thread-vs-fiber/polyphony_server.rb +13 -36
  41. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  42. data/examples/performance/xx-array.rb +11 -0
  43. data/examples/performance/xx-fiber-switch.rb +9 -0
  44. data/examples/performance/xx-snooze.rb +15 -0
  45. data/ext/{gyro → polyphony}/extconf.rb +2 -2
  46. data/ext/{gyro → polyphony}/fiber.c +18 -22
  47. data/ext/{gyro → polyphony}/libev.c +0 -0
  48. data/ext/{gyro → polyphony}/libev.h +0 -0
  49. data/ext/polyphony/libev_agent.c +718 -0
  50. data/ext/polyphony/libev_queue.c +216 -0
  51. data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -46
  52. data/ext/{gyro/gyro.h → polyphony/polyphony.h} +25 -39
  53. data/ext/polyphony/polyphony_ext.c +23 -0
  54. data/ext/{gyro → polyphony}/socket.c +21 -18
  55. data/ext/polyphony/thread.c +206 -0
  56. data/ext/{gyro → polyphony}/tracing.c +1 -1
  57. data/lib/polyphony.rb +40 -44
  58. data/lib/polyphony/adapters/fs.rb +1 -4
  59. data/lib/polyphony/adapters/irb.rb +1 -1
  60. data/lib/polyphony/adapters/postgres.rb +6 -5
  61. data/lib/polyphony/adapters/process.rb +27 -23
  62. data/lib/polyphony/adapters/trace.rb +110 -105
  63. data/lib/polyphony/core/channel.rb +35 -35
  64. data/lib/polyphony/core/exceptions.rb +29 -29
  65. data/lib/polyphony/core/global_api.rb +94 -91
  66. data/lib/polyphony/core/resource_pool.rb +83 -83
  67. data/lib/polyphony/core/sync.rb +16 -16
  68. data/lib/polyphony/core/thread_pool.rb +49 -37
  69. data/lib/polyphony/core/throttler.rb +30 -23
  70. data/lib/polyphony/event.rb +27 -0
  71. data/lib/polyphony/extensions/core.rb +25 -17
  72. data/lib/polyphony/extensions/fiber.rb +269 -267
  73. data/lib/polyphony/extensions/io.rb +56 -26
  74. data/lib/polyphony/extensions/openssl.rb +5 -9
  75. data/lib/polyphony/extensions/socket.rb +29 -10
  76. data/lib/polyphony/extensions/thread.rb +19 -12
  77. data/lib/polyphony/net.rb +64 -60
  78. data/lib/polyphony/version.rb +1 -1
  79. data/polyphony.gemspec +4 -7
  80. data/test/helper.rb +14 -1
  81. data/test/stress.rb +17 -12
  82. data/test/test_agent.rb +124 -0
  83. data/test/{test_async.rb → test_event.rb} +15 -7
  84. data/test/test_ext.rb +25 -4
  85. data/test/test_fiber.rb +19 -10
  86. data/test/test_global_api.rb +4 -4
  87. data/test/test_io.rb +46 -24
  88. data/test/test_queue.rb +74 -0
  89. data/test/test_signal.rb +3 -40
  90. data/test/test_socket.rb +33 -0
  91. data/test/test_thread.rb +38 -16
  92. data/test/test_thread_pool.rb +2 -2
  93. data/test/test_throttler.rb +0 -1
  94. data/test/test_trace.rb +6 -5
  95. metadata +41 -57
  96. data/docs/_includes/nav.html +0 -51
  97. data/docs/_includes/prevnext.html +0 -17
  98. data/docs/_layouts/default.html +0 -106
  99. data/docs/api-reference.md +0 -11
  100. data/docs/api-reference/gyro-async.md +0 -57
  101. data/docs/api-reference/gyro-child.md +0 -29
  102. data/docs/api-reference/gyro-queue.md +0 -44
  103. data/docs/api-reference/gyro-timer.md +0 -51
  104. data/docs/api-reference/gyro.md +0 -25
  105. data/docs/getting-started.md +0 -10
  106. data/docs/main-concepts.md +0 -10
  107. data/docs/user-guide.md +0 -10
  108. data/examples/core/forever_sleep.rb +0 -19
  109. data/ext/gyro/async.c +0 -148
  110. data/ext/gyro/child.c +0 -127
  111. data/ext/gyro/gyro_ext.c +0 -33
  112. data/ext/gyro/io.c +0 -474
  113. data/ext/gyro/queue.c +0 -142
  114. data/ext/gyro/selector.c +0 -205
  115. data/ext/gyro/signal.c +0 -118
  116. data/ext/gyro/thread.c +0 -298
  117. data/ext/gyro/timer.c +0 -134
  118. data/test/test_timer.rb +0 -56
@@ -1,142 +0,0 @@
1
- #include "gyro.h"
2
-
3
- struct Gyro_Queue {
4
- VALUE queue;
5
- VALUE wait_queue;
6
- };
7
-
8
- VALUE cGyro_Queue = Qnil;
9
-
10
- static void Gyro_Queue_mark(void *ptr) {
11
- struct Gyro_Queue *queue = ptr;
12
- if (queue->queue != Qnil) {
13
- rb_gc_mark(queue->queue);
14
- }
15
- if (queue->wait_queue != Qnil) {
16
- rb_gc_mark(queue->wait_queue);
17
- }
18
- }
19
-
20
- static void Gyro_Queue_free(void *ptr) {
21
- struct Gyro_Queue *queue = ptr;
22
- xfree(queue);
23
- }
24
-
25
- static size_t Gyro_Queue_size(const void *ptr) {
26
- return sizeof(struct Gyro_Queue);
27
- }
28
-
29
- static const rb_data_type_t Gyro_Queue_type = {
30
- "Gyro_Queue",
31
- {Gyro_Queue_mark, Gyro_Queue_free, Gyro_Queue_size,},
32
- 0, 0, 0
33
- };
34
-
35
- static VALUE Gyro_Queue_allocate(VALUE klass) {
36
- struct Gyro_Queue *queue = ALLOC(struct Gyro_Queue);
37
- return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
38
- }
39
- #define GetGyro_Queue(obj, queue) \
40
- TypedData_Get_Struct((obj), struct Gyro_Queue, &Gyro_Queue_type, (queue))
41
-
42
- static VALUE Gyro_Queue_initialize(VALUE self) {
43
- struct Gyro_Queue *queue;
44
- GetGyro_Queue(self, queue);
45
-
46
- queue->queue = rb_ary_new();
47
- queue->wait_queue = rb_ary_new();
48
-
49
- return Qnil;
50
- }
51
-
52
- VALUE Gyro_Queue_push(VALUE self, VALUE value) {
53
- struct Gyro_Queue *queue;
54
- GetGyro_Queue(self, queue);
55
-
56
- if (RARRAY_LEN(queue->wait_queue) > 0) {
57
- VALUE async = rb_ary_shift(queue->wait_queue);
58
- rb_funcall(async, ID_signal, 1, Qnil);
59
- }
60
-
61
- rb_ary_push(queue->queue, value);
62
- return self;
63
- }
64
-
65
- VALUE Gyro_Queue_shift(VALUE self) {
66
- struct Gyro_Queue *queue;
67
- GetGyro_Queue(self, queue);
68
-
69
- if (RARRAY_LEN(queue->queue) == 0) {
70
- VALUE async = Fiber_auto_async(rb_fiber_current());
71
- rb_ary_push(queue->wait_queue, async);
72
- VALUE ret = Gyro_Async_await_no_raise(async);
73
- if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
74
- rb_ary_delete(queue->wait_queue, async);
75
- return rb_funcall(rb_mKernel, ID_raise, 1, ret);
76
- }
77
- RB_GC_GUARD(ret);
78
- }
79
-
80
- return rb_ary_shift(queue->queue);
81
- }
82
-
83
- VALUE Gyro_Queue_shift_no_wait(VALUE self) {
84
- struct Gyro_Queue *queue;
85
- GetGyro_Queue(self, queue);
86
-
87
- return rb_ary_shift(queue->queue);
88
- }
89
-
90
- VALUE Gyro_Queue_shift_each(VALUE self) {
91
- struct Gyro_Queue *queue;
92
- GetGyro_Queue(self, queue);
93
-
94
- VALUE old_queue = queue->queue;
95
- queue->queue = rb_ary_new();
96
-
97
- if (rb_block_given_p()) {
98
- long len = RARRAY_LEN(old_queue);
99
- long i;
100
- for (i = 0; i < len; i++) {
101
- rb_yield(RARRAY_AREF(old_queue, i));
102
- }
103
- RB_GC_GUARD(old_queue);
104
- return self;
105
- }
106
- else {
107
- return old_queue;
108
- }
109
- }
110
-
111
- VALUE Gyro_Queue_clear(VALUE self) {
112
- struct Gyro_Queue *queue;
113
- GetGyro_Queue(self, queue);
114
-
115
- rb_ary_clear(queue->queue);
116
- return self;
117
- }
118
-
119
- VALUE Gyro_Queue_empty_p(VALUE self) {
120
- struct Gyro_Queue *queue;
121
- GetGyro_Queue(self, queue);
122
-
123
- return (RARRAY_LEN(queue->queue) == 0) ? Qtrue : Qfalse;
124
- }
125
-
126
- void Init_Gyro_Queue() {
127
- cGyro_Queue = rb_define_class_under(mGyro, "Queue", rb_cData);
128
- rb_define_alloc_func(cGyro_Queue, Gyro_Queue_allocate);
129
-
130
- rb_define_method(cGyro_Queue, "initialize", Gyro_Queue_initialize, 0);
131
- rb_define_method(cGyro_Queue, "push", Gyro_Queue_push, 1);
132
- rb_define_method(cGyro_Queue, "<<", Gyro_Queue_push, 1);
133
-
134
- rb_define_method(cGyro_Queue, "pop", Gyro_Queue_shift, 0);
135
- rb_define_method(cGyro_Queue, "shift", Gyro_Queue_shift, 0);
136
-
137
- rb_define_method(cGyro_Queue, "shift_no_wait", Gyro_Queue_shift_no_wait, 0);
138
-
139
- rb_define_method(cGyro_Queue, "shift_each", Gyro_Queue_shift_each, 0);
140
- rb_define_method(cGyro_Queue, "clear", Gyro_Queue_clear, 0);
141
- rb_define_method(cGyro_Queue, "empty?", Gyro_Queue_empty_p, 0);
142
- }
@@ -1,205 +0,0 @@
1
- #include "gyro.h"
2
-
3
- struct Gyro_Selector {
4
- struct ev_loop *ev_loop;
5
- long run_no_wait_count;
6
- int ev_loop_running;
7
- struct ev_async async;
8
- VALUE active_watchers;
9
- };
10
-
11
- VALUE cGyro_Selector = Qnil;
12
-
13
- static void Gyro_Selector_mark(void *ptr) {
14
- struct Gyro_Selector *selector = ptr;
15
- rb_gc_mark(selector->active_watchers);
16
- }
17
-
18
- static void Gyro_Selector_free(void *ptr) {
19
- struct Gyro_Selector *selector = ptr;
20
- ev_async_stop(selector->ev_loop, &selector->async);
21
- if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
22
- ev_loop_destroy(selector->ev_loop);
23
- }
24
- xfree(selector);
25
- }
26
-
27
- static size_t Gyro_Selector_size(const void *ptr) {
28
- return sizeof(struct Gyro_Selector);
29
- }
30
-
31
- static const rb_data_type_t Gyro_Selector_type = {
32
- "Gyro_Selector",
33
- {Gyro_Selector_mark, Gyro_Selector_free, Gyro_Selector_size,},
34
- 0, 0, 0
35
- };
36
-
37
- static VALUE Gyro_Selector_allocate(VALUE klass) {
38
- struct Gyro_Selector *selector = ALLOC(struct Gyro_Selector);
39
- return TypedData_Wrap_Struct(klass, &Gyro_Selector_type, selector);
40
- }
41
-
42
- #define GetGyro_Selector(obj, selector) \
43
- TypedData_Get_Struct((obj), struct Gyro_Selector, &Gyro_Selector_type, (selector))
44
-
45
- inline struct ev_loop *Gyro_Selector_ev_loop(VALUE self) {
46
- struct Gyro_Selector *selector;
47
- GetGyro_Selector(self, selector);
48
-
49
- return selector->ev_loop;
50
- }
51
-
52
- inline struct ev_loop *Gyro_Selector_current_thread_ev_loop() {
53
- struct Gyro_Selector *selector;
54
- GetGyro_Selector(Thread_current_event_selector(), selector);
55
-
56
- return selector->ev_loop;
57
- }
58
-
59
- inline ev_tstamp Gyro_Selector_now(VALUE self) {
60
- struct Gyro_Selector *selector;
61
- GetGyro_Selector(self, selector);
62
-
63
- return ev_now(selector->ev_loop);
64
- }
65
-
66
- long Gyro_Selector_pending_count(VALUE self) {
67
- struct Gyro_Selector *selector;
68
- GetGyro_Selector(self, selector);
69
-
70
- return ev_pending_count(selector->ev_loop);
71
- }
72
-
73
- void dummy_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
74
- // This callback does nothing, the selector's async is used solely for waking
75
- // up the event loop.
76
- }
77
-
78
- inline void Gyro_Selector_run_ev_loop(struct Gyro_Selector *selector, int flags) {
79
- selector->ev_loop_running = 1;
80
- ev_run(selector->ev_loop, flags);
81
- selector->ev_loop_running = 0;
82
- }
83
-
84
- static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
85
- struct Gyro_Selector *selector;
86
- GetGyro_Selector(self, selector);
87
-
88
- int use_default_loop = (rb_thread_current() == rb_thread_main());
89
- selector->ev_loop = use_default_loop ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
90
- selector->run_no_wait_count = 0;
91
-
92
- selector->active_watchers = rb_hash_new();
93
-
94
- ev_async_init(&selector->async, dummy_async_callback);
95
- ev_async_start(selector->ev_loop, &selector->async);
96
- Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
97
- return Qnil;
98
- }
99
-
100
- inline void Gyro_Selector_add_active_watcher(VALUE self, VALUE watcher) {
101
- struct Gyro_Selector *selector;
102
- GetGyro_Selector(self, selector);
103
-
104
- rb_hash_aset(selector->active_watchers, watcher, Qtrue);
105
- }
106
-
107
- inline void Gyro_Selector_remove_active_watcher(VALUE self, VALUE watcher) {
108
- struct Gyro_Selector *selector;
109
- GetGyro_Selector(self, selector);
110
-
111
- rb_hash_delete(selector->active_watchers, watcher);
112
- }
113
-
114
- inline VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber) {
115
- struct Gyro_Selector *selector;
116
- GetGyro_Selector(self, selector);
117
- if (selector->ev_loop) {
118
- selector->run_no_wait_count = 0;
119
- FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
120
- Gyro_Selector_run_ev_loop(selector, EVRUN_ONCE);
121
- FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
122
- }
123
- return Qnil;
124
- }
125
-
126
- inline void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runnable_count) {
127
- struct Gyro_Selector *selector;
128
- GetGyro_Selector(self, selector);
129
-
130
- selector->run_no_wait_count++;
131
- if (selector->run_no_wait_count < runnable_count || selector->run_no_wait_count < 10) {
132
- return;
133
- }
134
-
135
- selector->run_no_wait_count = 0;
136
- FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
137
- Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
138
- FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
139
- }
140
-
141
- VALUE Gyro_Selector_stop(VALUE self) {
142
- struct Gyro_Selector *selector;
143
- GetGyro_Selector(self, selector);
144
-
145
- if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
146
- // ev_loop_destroy(selector->ev_loop);
147
- // selector->ev_loop = 0;
148
- }
149
- return Qnil;
150
- }
151
-
152
- VALUE Gyro_Selector_post_fork(VALUE self) {
153
- struct Gyro_Selector *selector;
154
- GetGyro_Selector(self, selector);
155
-
156
- ev_loop_fork(selector->ev_loop);
157
- return self;
158
- }
159
-
160
- VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self) {
161
- struct Gyro_Selector *selector;
162
- GetGyro_Selector(self, selector);
163
-
164
- if (selector->ev_loop_running) {
165
- // Since the loop will run until at least one event has occurred, we signal
166
- // the selector's associated async watcher, which will cause the ev loop to
167
- // return. In contrast to using `ev_break` to break out of the loop, which
168
- // should be called from the same thread (from within the ev_loop), using an
169
- // `ev_async` allows us to interrupt the event loop across threads.
170
- ev_async_send(selector->ev_loop, &selector->async);
171
- return Qtrue;
172
- }
173
-
174
- return Qnil;
175
- }
176
-
177
- inline static VALUE Gyro_Selector_wait_readable(VALUE self, VALUE io) {
178
- VALUE watcher = IO_read_watcher(io);
179
- return Gyro_IO_await(watcher);
180
- }
181
-
182
- inline static VALUE Gyro_Selector_wait_writable(VALUE self, VALUE io) {
183
- VALUE watcher = IO_write_watcher(io);
184
- return Gyro_IO_await(watcher);
185
- }
186
-
187
- inline static VALUE Gyro_Selector_wait_timeout(VALUE self, VALUE duration) {
188
- VALUE watcher = rb_funcall(cGyro_Timer, ID_new, 2, duration, Qnil);
189
- VALUE ret = Gyro_Timer_await(watcher);
190
- RB_GC_GUARD(watcher);
191
- return ret;
192
- }
193
-
194
- void Init_Gyro_Selector() {
195
- cGyro_Selector = rb_define_class_under(mGyro, "Selector", rb_cData);
196
- rb_define_alloc_func(cGyro_Selector, Gyro_Selector_allocate);
197
-
198
- rb_define_method(cGyro_Selector, "initialize", Gyro_Selector_initialize, 1);
199
- rb_define_method(cGyro_Selector, "run", Gyro_Selector_run, 1);
200
- rb_define_method(cGyro_Selector, "stop", Gyro_Selector_stop, 0);
201
- rb_define_method(cGyro_Selector, "wait_readable", Gyro_Selector_wait_readable, 1);
202
- rb_define_method(cGyro_Selector, "wait_writable", Gyro_Selector_wait_writable, 1);
203
- rb_define_method(cGyro_Selector, "wait_timeout", Gyro_Selector_wait_timeout, 1);
204
- rb_define_method(cGyro_Selector, "break_out_of_ev_loop", Gyro_Selector_break_out_of_ev_loop, 0);
205
- }
@@ -1,118 +0,0 @@
1
- #include "gyro.h"
2
-
3
- struct Gyro_Signal {
4
- struct ev_signal ev_signal;
5
- struct ev_loop *ev_loop;
6
- int active;
7
- int signum;
8
- VALUE self;
9
- VALUE fiber;
10
- VALUE selector;
11
- };
12
-
13
- static VALUE cGyro_Signal = Qnil;
14
-
15
- static void Gyro_Signal_mark(void *ptr) {
16
- struct Gyro_Signal *signal = ptr;
17
- if (signal->fiber != Qnil) {
18
- rb_gc_mark(signal->fiber);
19
- }
20
- if (signal->selector != Qnil) {
21
- rb_gc_mark(signal->selector);
22
- }
23
- }
24
-
25
- static void Gyro_Signal_free(void *ptr) {
26
- struct Gyro_Signal *signal = ptr;
27
- if (signal->active) {
28
- ev_clear_pending(signal->ev_loop, &signal->ev_signal);
29
- ev_signal_stop(signal->ev_loop, &signal->ev_signal);
30
- }
31
- xfree(signal);
32
- }
33
-
34
- static size_t Gyro_Signal_size(const void *ptr) {
35
- return sizeof(struct Gyro_Signal);
36
- }
37
-
38
- static const rb_data_type_t Gyro_Signal_type = {
39
- "Gyro_Signal",
40
- {Gyro_Signal_mark, Gyro_Signal_free, Gyro_Signal_size,},
41
- 0, 0, 0
42
- };
43
-
44
- static VALUE Gyro_Signal_allocate(VALUE klass) {
45
- struct Gyro_Signal *signal = ALLOC(struct Gyro_Signal);
46
- return TypedData_Wrap_Struct(klass, &Gyro_Signal_type, signal);
47
- }
48
-
49
- inline void Gyro_Signal_activate(struct Gyro_Signal *signal) {
50
- if (signal->active) return;
51
-
52
- signal->active = 1;
53
- signal->fiber = rb_fiber_current();
54
- signal->selector = Thread_current_event_selector();
55
- signal->ev_loop = Gyro_Selector_ev_loop(signal->selector);
56
- Gyro_Selector_add_active_watcher(signal->selector, signal->self);
57
- ev_signal_start(signal->ev_loop, &signal->ev_signal);
58
- }
59
-
60
- inline void Gyro_Signal_deactivate(struct Gyro_Signal *signal) {
61
- if (!signal->active) return;
62
-
63
- ev_signal_stop(signal->ev_loop, &signal->ev_signal);
64
- Gyro_Selector_remove_active_watcher(signal->selector, signal->self);
65
- signal->active = 0;
66
- signal->ev_loop = 0;
67
- signal->selector = Qnil;
68
- signal->fiber = Qnil;
69
- }
70
-
71
- void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
72
- struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
73
-
74
- Fiber_make_runnable(signal->fiber, INT2NUM(signal->signum));
75
- Gyro_Signal_deactivate(signal);
76
- }
77
-
78
- #define GetGyro_Signal(obj, signal) \
79
- TypedData_Get_Struct((obj), struct Gyro_Signal, &Gyro_Signal_type, (signal))
80
-
81
- static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
82
- struct Gyro_Signal *signal;
83
- VALUE signum = sig;
84
-
85
- GetGyro_Signal(self, signal);
86
-
87
- signal->self = self;
88
- signal->fiber = Qnil;
89
- signal->selector = Qnil;
90
- signal->signum = NUM2INT(signum);
91
- signal->active = 0;
92
- signal->ev_loop = 0;
93
-
94
- ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
95
-
96
- return Qnil;
97
- }
98
-
99
- static VALUE Gyro_Signal_await(VALUE self) {
100
- struct Gyro_Signal *signal;
101
- GetGyro_Signal(self, signal);
102
-
103
- Gyro_Signal_activate(signal);
104
- VALUE ret = Gyro_switchpoint();
105
- Gyro_Signal_deactivate(signal);
106
-
107
- TEST_RESUME_EXCEPTION(ret);
108
- RB_GC_GUARD(ret);
109
- return ret;
110
- }
111
-
112
- void Init_Gyro_Signal() {
113
- cGyro_Signal = rb_define_class_under(mGyro, "Signal", rb_cData);
114
- rb_define_alloc_func(cGyro_Signal, Gyro_Signal_allocate);
115
-
116
- rb_define_method(cGyro_Signal, "initialize", Gyro_Signal_initialize, 1);
117
- rb_define_method(cGyro_Signal, "await", Gyro_Signal_await, 0);
118
- }