polyphony 0.34 → 0.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +11 -2
- data/.gitignore +2 -2
- data/.rubocop.yml +30 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +0 -11
- data/Gemfile.lock +11 -10
- data/README.md +2 -1
- data/Rakefile +6 -2
- data/TODO.md +18 -95
- data/docs/_includes/head.html +40 -0
- data/docs/_includes/nav.html +5 -5
- data/docs/api-reference.md +1 -1
- data/docs/api-reference/fiber.md +18 -0
- data/docs/api-reference/gyro-async.md +57 -0
- data/docs/api-reference/gyro-child.md +29 -0
- data/docs/api-reference/gyro-queue.md +44 -0
- data/docs/api-reference/gyro-timer.md +51 -0
- data/docs/api-reference/gyro.md +25 -0
- data/docs/index.md +10 -7
- data/docs/main-concepts/design-principles.md +67 -9
- data/docs/main-concepts/extending.md +1 -1
- data/docs/main-concepts/fiber-scheduling.md +55 -72
- data/examples/core/xx-agent.rb +102 -0
- data/examples/core/xx-fork-cleanup.rb +22 -0
- data/examples/core/xx-sleeping.rb +14 -6
- data/examples/core/xx-timer-gc.rb +17 -0
- data/examples/io/tunnel.rb +48 -0
- data/examples/io/xx-irb.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +14 -25
- data/ext/{gyro → polyphony}/extconf.rb +2 -2
- data/ext/polyphony/fiber.c +112 -0
- data/ext/{gyro → polyphony}/libev.c +0 -0
- data/ext/{gyro → polyphony}/libev.h +0 -0
- data/ext/polyphony/libev_agent.c +503 -0
- data/ext/polyphony/libev_queue.c +214 -0
- data/ext/polyphony/polyphony.c +89 -0
- data/ext/{gyro/gyro.h → polyphony/polyphony.h} +49 -59
- data/ext/polyphony/polyphony_ext.c +23 -0
- data/ext/{gyro → polyphony}/socket.c +21 -19
- data/ext/{gyro → polyphony}/thread.c +55 -119
- data/ext/{gyro → polyphony}/tracing.c +1 -1
- data/lib/polyphony.rb +37 -44
- data/lib/polyphony/adapters/fs.rb +1 -4
- data/lib/polyphony/adapters/irb.rb +2 -2
- data/lib/polyphony/adapters/postgres.rb +6 -5
- data/lib/polyphony/adapters/process.rb +27 -23
- data/lib/polyphony/adapters/trace.rb +110 -105
- data/lib/polyphony/core/channel.rb +35 -35
- data/lib/polyphony/core/exceptions.rb +29 -29
- data/lib/polyphony/core/global_api.rb +94 -91
- data/lib/polyphony/core/resource_pool.rb +83 -83
- data/lib/polyphony/core/sync.rb +16 -16
- data/lib/polyphony/core/thread_pool.rb +49 -37
- data/lib/polyphony/core/throttler.rb +30 -23
- data/lib/polyphony/event.rb +27 -0
- data/lib/polyphony/extensions/core.rb +23 -14
- data/lib/polyphony/extensions/fiber.rb +269 -267
- data/lib/polyphony/extensions/io.rb +56 -26
- data/lib/polyphony/extensions/openssl.rb +5 -9
- data/lib/polyphony/extensions/socket.rb +29 -10
- data/lib/polyphony/extensions/thread.rb +19 -12
- data/lib/polyphony/net.rb +64 -60
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +3 -6
- data/test/helper.rb +14 -1
- data/test/stress.rb +17 -12
- data/test/test_agent.rb +77 -0
- data/test/{test_async.rb → test_event.rb} +17 -9
- data/test/test_ext.rb +25 -4
- data/test/test_fiber.rb +23 -14
- data/test/test_global_api.rb +5 -5
- data/test/test_io.rb +46 -24
- data/test/test_queue.rb +74 -0
- data/test/test_signal.rb +3 -40
- data/test/test_socket.rb +33 -0
- data/test/test_thread.rb +38 -16
- data/test/test_thread_pool.rb +3 -3
- data/test/test_throttler.rb +0 -1
- data/test/test_trace.rb +6 -5
- metadata +34 -39
- data/ext/gyro/async.c +0 -158
- data/ext/gyro/child.c +0 -117
- data/ext/gyro/gyro.c +0 -203
- data/ext/gyro/gyro_ext.c +0 -31
- data/ext/gyro/io.c +0 -447
- data/ext/gyro/queue.c +0 -142
- data/ext/gyro/selector.c +0 -183
- data/ext/gyro/signal.c +0 -108
- data/ext/gyro/timer.c +0 -154
- data/test/test_timer.rb +0 -56
data/ext/gyro/queue.c
DELETED
@@ -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,
|
33
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
34
|
-
};
|
35
|
-
|
36
|
-
static VALUE Gyro_Queue_allocate(VALUE klass) {
|
37
|
-
struct Gyro_Queue *queue = (struct Gyro_Queue *)xmalloc(sizeof(struct Gyro_Queue));
|
38
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
|
39
|
-
}
|
40
|
-
#define GetGyro_Queue(obj, queue) \
|
41
|
-
TypedData_Get_Struct((obj), struct Gyro_Queue, &Gyro_Queue_type, (queue))
|
42
|
-
|
43
|
-
static VALUE Gyro_Queue_initialize(VALUE self) {
|
44
|
-
struct Gyro_Queue *queue;
|
45
|
-
GetGyro_Queue(self, queue);
|
46
|
-
|
47
|
-
queue->queue = rb_ary_new();
|
48
|
-
queue->wait_queue = rb_ary_new();
|
49
|
-
|
50
|
-
return Qnil;
|
51
|
-
}
|
52
|
-
|
53
|
-
VALUE Gyro_Queue_push(VALUE self, VALUE value) {
|
54
|
-
struct Gyro_Queue *queue;
|
55
|
-
GetGyro_Queue(self, queue);
|
56
|
-
|
57
|
-
if (RARRAY_LEN(queue->wait_queue) > 0) {
|
58
|
-
VALUE async = rb_ary_shift(queue->wait_queue);
|
59
|
-
rb_funcall(async, ID_signal_bang, 1, Qnil);
|
60
|
-
}
|
61
|
-
|
62
|
-
rb_ary_push(queue->queue, value);
|
63
|
-
return self;
|
64
|
-
}
|
65
|
-
|
66
|
-
VALUE Gyro_Queue_shift(VALUE self) {
|
67
|
-
struct Gyro_Queue *queue;
|
68
|
-
GetGyro_Queue(self, queue);
|
69
|
-
|
70
|
-
if (RARRAY_LEN(queue->queue) == 0) {
|
71
|
-
VALUE async = rb_funcall(cGyro_Async, ID_new, 0);
|
72
|
-
rb_ary_push(queue->wait_queue, async);
|
73
|
-
VALUE ret = Gyro_Async_await_no_raise(async);
|
74
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
75
|
-
rb_ary_delete(queue->wait_queue, async);
|
76
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
77
|
-
}
|
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
|
-
}
|
data/ext/gyro/selector.c
DELETED
@@ -1,183 +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
|
-
};
|
9
|
-
|
10
|
-
VALUE cGyro_Selector = Qnil;
|
11
|
-
|
12
|
-
static void Gyro_Selector_mark(void *ptr) {
|
13
|
-
// struct Gyro_Selector *selector = ptr;
|
14
|
-
}
|
15
|
-
|
16
|
-
static void Gyro_Selector_free(void *ptr) {
|
17
|
-
struct Gyro_Selector *selector = ptr;
|
18
|
-
ev_async_stop(selector->ev_loop, &selector->async);
|
19
|
-
if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
|
20
|
-
// printf("Selector garbage collected before being stopped!\n");
|
21
|
-
ev_loop_destroy(selector->ev_loop);
|
22
|
-
}
|
23
|
-
xfree(selector);
|
24
|
-
}
|
25
|
-
|
26
|
-
static size_t Gyro_Selector_size(const void *ptr) {
|
27
|
-
return sizeof(struct Gyro_Selector);
|
28
|
-
}
|
29
|
-
|
30
|
-
static const rb_data_type_t Gyro_Selector_type = {
|
31
|
-
"Gyro_Selector",
|
32
|
-
{Gyro_Selector_mark, Gyro_Selector_free, Gyro_Selector_size,},
|
33
|
-
0, 0,
|
34
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
35
|
-
};
|
36
|
-
|
37
|
-
static VALUE Gyro_Selector_allocate(VALUE klass) {
|
38
|
-
struct Gyro_Selector *selector = (struct Gyro_Selector *)xmalloc(sizeof(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
|
-
static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
|
79
|
-
struct Gyro_Selector *selector;
|
80
|
-
GetGyro_Selector(self, selector);
|
81
|
-
|
82
|
-
int use_default_loop = (rb_thread_current() == rb_thread_main());
|
83
|
-
selector->ev_loop = use_default_loop ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
|
84
|
-
selector->run_no_wait_count = 0;
|
85
|
-
|
86
|
-
ev_async_init(&selector->async, dummy_async_callback);
|
87
|
-
ev_async_start(selector->ev_loop, &selector->async);
|
88
|
-
ev_run(selector->ev_loop, EVRUN_NOWAIT);
|
89
|
-
return Qnil;
|
90
|
-
}
|
91
|
-
|
92
|
-
inline VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber) {
|
93
|
-
struct Gyro_Selector *selector;
|
94
|
-
GetGyro_Selector(self, selector);
|
95
|
-
if (selector->ev_loop) {
|
96
|
-
selector->run_no_wait_count = 0;
|
97
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
98
|
-
selector->ev_loop_running = 1;
|
99
|
-
ev_run(selector->ev_loop, EVRUN_ONCE);
|
100
|
-
selector->ev_loop_running = 0;
|
101
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
102
|
-
}
|
103
|
-
return Qnil;
|
104
|
-
}
|
105
|
-
|
106
|
-
inline void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runnable_count) {
|
107
|
-
struct Gyro_Selector *selector;
|
108
|
-
GetGyro_Selector(self, selector);
|
109
|
-
|
110
|
-
selector->run_no_wait_count++;
|
111
|
-
if (selector->run_no_wait_count < runnable_count || selector->run_no_wait_count < 10) {
|
112
|
-
return;
|
113
|
-
}
|
114
|
-
|
115
|
-
selector->run_no_wait_count = 0;
|
116
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
117
|
-
ev_run(selector->ev_loop, EVRUN_NOWAIT);
|
118
|
-
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
119
|
-
}
|
120
|
-
|
121
|
-
VALUE Gyro_Selector_stop(VALUE self) {
|
122
|
-
struct Gyro_Selector *selector;
|
123
|
-
GetGyro_Selector(self, selector);
|
124
|
-
|
125
|
-
if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
|
126
|
-
// ev_loop_destroy(selector->ev_loop);
|
127
|
-
// selector->ev_loop = 0;
|
128
|
-
}
|
129
|
-
return Qnil;
|
130
|
-
}
|
131
|
-
|
132
|
-
VALUE Gyro_Selector_post_fork(VALUE self) {
|
133
|
-
struct Gyro_Selector *selector;
|
134
|
-
GetGyro_Selector(self, selector);
|
135
|
-
|
136
|
-
ev_loop_fork(selector->ev_loop);
|
137
|
-
return self;
|
138
|
-
}
|
139
|
-
|
140
|
-
VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self) {
|
141
|
-
struct Gyro_Selector *selector;
|
142
|
-
GetGyro_Selector(self, selector);
|
143
|
-
|
144
|
-
if (selector->ev_loop_running) {
|
145
|
-
// Since the loop will run until at least one event has occurred, we signal
|
146
|
-
// the selector's associated async watcher, which will cause the ev loop to
|
147
|
-
// return. In contrast to using `ev_break` to break out of the loop, which
|
148
|
-
// should be called from the same thread (from within the ev_loop), using an
|
149
|
-
// `ev_async` allows us to interrupt the event loop across threads.
|
150
|
-
ev_async_send(selector->ev_loop, &selector->async);
|
151
|
-
return Qtrue;
|
152
|
-
}
|
153
|
-
|
154
|
-
return Qnil;
|
155
|
-
}
|
156
|
-
|
157
|
-
inline static VALUE Gyro_Selector_wait_readable(VALUE self, VALUE io) {
|
158
|
-
VALUE watcher = IO_read_watcher(io);
|
159
|
-
return Gyro_IO_await(watcher);
|
160
|
-
}
|
161
|
-
|
162
|
-
inline static VALUE Gyro_Selector_wait_writable(VALUE self, VALUE io) {
|
163
|
-
VALUE watcher = IO_write_watcher(io);
|
164
|
-
return Gyro_IO_await(watcher);
|
165
|
-
}
|
166
|
-
|
167
|
-
inline static VALUE Gyro_Selector_wait_timeout(VALUE self, VALUE duration) {
|
168
|
-
VALUE watcher = rb_funcall(cGyro_Timer, ID_new, 2, duration, Qnil);
|
169
|
-
return Gyro_Timer_await(watcher);
|
170
|
-
}
|
171
|
-
|
172
|
-
void Init_Gyro_Selector() {
|
173
|
-
cGyro_Selector = rb_define_class_under(mGyro, "Selector", rb_cData);
|
174
|
-
rb_define_alloc_func(cGyro_Selector, Gyro_Selector_allocate);
|
175
|
-
|
176
|
-
rb_define_method(cGyro_Selector, "initialize", Gyro_Selector_initialize, 1);
|
177
|
-
rb_define_method(cGyro_Selector, "run", Gyro_Selector_run, 1);
|
178
|
-
rb_define_method(cGyro_Selector, "stop", Gyro_Selector_stop, 0);
|
179
|
-
rb_define_method(cGyro_Selector, "wait_readable", Gyro_Selector_wait_readable, 1);
|
180
|
-
rb_define_method(cGyro_Selector, "wait_writable", Gyro_Selector_wait_writable, 1);
|
181
|
-
rb_define_method(cGyro_Selector, "wait_timeout", Gyro_Selector_wait_timeout, 1);
|
182
|
-
rb_define_method(cGyro_Selector, "break_out_of_ev_loop", Gyro_Selector_break_out_of_ev_loop, 0);
|
183
|
-
}
|
data/ext/gyro/signal.c
DELETED
@@ -1,108 +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 fiber;
|
9
|
-
};
|
10
|
-
|
11
|
-
static VALUE cGyro_Signal = Qnil;
|
12
|
-
|
13
|
-
static void Gyro_Signal_mark(void *ptr) {
|
14
|
-
struct Gyro_Signal *signal = ptr;
|
15
|
-
if (signal->fiber != Qnil) {
|
16
|
-
rb_gc_mark(signal->fiber);
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
static void Gyro_Signal_free(void *ptr) {
|
21
|
-
struct Gyro_Signal *signal = ptr;
|
22
|
-
if (signal->active) {
|
23
|
-
printf("Signal watcher garbage collected while still active!\n");
|
24
|
-
// ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
25
|
-
}
|
26
|
-
xfree(signal);
|
27
|
-
}
|
28
|
-
|
29
|
-
static size_t Gyro_Signal_size(const void *ptr) {
|
30
|
-
return sizeof(struct Gyro_Signal);
|
31
|
-
}
|
32
|
-
|
33
|
-
static const rb_data_type_t Gyro_Signal_type = {
|
34
|
-
"Gyro_Signal",
|
35
|
-
{Gyro_Signal_mark, Gyro_Signal_free, Gyro_Signal_size,},
|
36
|
-
0, 0,
|
37
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
38
|
-
};
|
39
|
-
|
40
|
-
static VALUE Gyro_Signal_allocate(VALUE klass) {
|
41
|
-
struct Gyro_Signal *signal = (struct Gyro_Signal *)xmalloc(sizeof(struct Gyro_Signal));
|
42
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Signal_type, signal);
|
43
|
-
}
|
44
|
-
|
45
|
-
void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
|
46
|
-
struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
|
47
|
-
|
48
|
-
if (signal->fiber != Qnil) {
|
49
|
-
VALUE fiber = signal->fiber;
|
50
|
-
|
51
|
-
ev_signal_stop(signal->ev_loop, ev_signal);
|
52
|
-
signal->active = 0;
|
53
|
-
signal->fiber = Qnil;
|
54
|
-
Gyro_schedule_fiber(fiber, INT2NUM(signal->signum));
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
#define GetGyro_Signal(obj, signal) \
|
59
|
-
TypedData_Get_Struct((obj), struct Gyro_Signal, &Gyro_Signal_type, (signal))
|
60
|
-
|
61
|
-
static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
62
|
-
struct Gyro_Signal *signal;
|
63
|
-
VALUE signum = sig;
|
64
|
-
|
65
|
-
GetGyro_Signal(self, signal);
|
66
|
-
signal->signum = NUM2INT(signum);
|
67
|
-
|
68
|
-
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
69
|
-
|
70
|
-
return Qnil;
|
71
|
-
}
|
72
|
-
|
73
|
-
static VALUE Gyro_Signal_await(VALUE self) {
|
74
|
-
struct Gyro_Signal *signal;
|
75
|
-
VALUE ret;
|
76
|
-
|
77
|
-
GetGyro_Signal(self, signal);
|
78
|
-
|
79
|
-
signal->fiber = rb_fiber_current();
|
80
|
-
signal->active = 1;
|
81
|
-
signal->ev_loop = Gyro_Selector_current_thread_ev_loop();
|
82
|
-
ev_signal_start(signal->ev_loop, &signal->ev_signal);
|
83
|
-
|
84
|
-
ret = Fiber_await();
|
85
|
-
RB_GC_GUARD(ret);
|
86
|
-
|
87
|
-
if (signal->active) {
|
88
|
-
signal->active = 0;
|
89
|
-
signal->fiber = Qnil;
|
90
|
-
ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
91
|
-
}
|
92
|
-
|
93
|
-
// fiber is resumed, check if resumed value is an exception
|
94
|
-
signal->fiber = Qnil;
|
95
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
96
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
97
|
-
}
|
98
|
-
else
|
99
|
-
return ret;
|
100
|
-
}
|
101
|
-
|
102
|
-
void Init_Gyro_Signal() {
|
103
|
-
cGyro_Signal = rb_define_class_under(mGyro, "Signal", rb_cData);
|
104
|
-
rb_define_alloc_func(cGyro_Signal, Gyro_Signal_allocate);
|
105
|
-
|
106
|
-
rb_define_method(cGyro_Signal, "initialize", Gyro_Signal_initialize, 1);
|
107
|
-
rb_define_method(cGyro_Signal, "await", Gyro_Signal_await, 0);
|
108
|
-
}
|
data/ext/gyro/timer.c
DELETED
@@ -1,154 +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
|
-
int should_free;
|
10
|
-
VALUE self;
|
11
|
-
VALUE fiber;
|
12
|
-
VALUE selector;
|
13
|
-
};
|
14
|
-
|
15
|
-
VALUE cGyro_Timer = Qnil;
|
16
|
-
|
17
|
-
static void Gyro_Timer_mark(void *ptr) {
|
18
|
-
struct Gyro_Timer *timer = ptr;
|
19
|
-
if (timer->fiber != Qnil) {
|
20
|
-
rb_gc_mark(timer->fiber);
|
21
|
-
}
|
22
|
-
if (timer->selector != Qnil) {
|
23
|
-
rb_gc_mark(timer->selector);
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
static void Gyro_Timer_free(void *ptr) {
|
28
|
-
struct Gyro_Timer *timer = ptr;
|
29
|
-
if (timer->active) {
|
30
|
-
printf("Timer watcher garbage collected while still active (%g, %g)!\n", timer->after, timer->repeat);
|
31
|
-
timer->should_free = 1;
|
32
|
-
} else {
|
33
|
-
xfree(timer);
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
static size_t Gyro_Timer_size(const void *ptr) {
|
38
|
-
return sizeof(struct Gyro_Timer);
|
39
|
-
}
|
40
|
-
|
41
|
-
static const rb_data_type_t Gyro_Timer_type = {
|
42
|
-
"Gyro_Timer",
|
43
|
-
{Gyro_Timer_mark, Gyro_Timer_free, Gyro_Timer_size,},
|
44
|
-
0, 0,
|
45
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
46
|
-
};
|
47
|
-
|
48
|
-
static VALUE Gyro_Timer_allocate(VALUE klass) {
|
49
|
-
struct Gyro_Timer *timer = (struct Gyro_Timer *)xmalloc(sizeof(struct Gyro_Timer));
|
50
|
-
return TypedData_Wrap_Struct(klass, &Gyro_Timer_type, timer);
|
51
|
-
}
|
52
|
-
#define GetGyro_Timer(obj, timer) \
|
53
|
-
TypedData_Get_Struct((obj), struct Gyro_Timer, &Gyro_Timer_type, (timer))
|
54
|
-
|
55
|
-
void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
|
56
|
-
struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
|
57
|
-
|
58
|
-
if (timer->should_free) {
|
59
|
-
ev_timer_stop(timer->ev_loop, ev_timer);
|
60
|
-
xfree(timer);
|
61
|
-
return;
|
62
|
-
}
|
63
|
-
|
64
|
-
if (!timer->repeat) {
|
65
|
-
timer->active = 0;
|
66
|
-
timer->selector = Qnil;
|
67
|
-
}
|
68
|
-
|
69
|
-
if (timer->fiber != Qnil) {
|
70
|
-
Gyro_schedule_fiber(timer->fiber, DBL2NUM(timer->after));
|
71
|
-
}
|
72
|
-
}
|
73
|
-
|
74
|
-
static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
|
75
|
-
struct Gyro_Timer *timer;
|
76
|
-
|
77
|
-
GetGyro_Timer(self, timer);
|
78
|
-
|
79
|
-
timer->self = self;
|
80
|
-
timer->fiber = Qnil;
|
81
|
-
timer->after = NUM2DBL(after);
|
82
|
-
timer->repeat = NUM2DBL(repeat);
|
83
|
-
timer->active = 0;
|
84
|
-
|
85
|
-
timer->should_free = 0;
|
86
|
-
|
87
|
-
ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
|
88
|
-
timer->ev_loop = 0;
|
89
|
-
timer->selector = Qnil;
|
90
|
-
|
91
|
-
return Qnil;
|
92
|
-
}
|
93
|
-
|
94
|
-
VALUE Gyro_Timer_stop(VALUE self) {
|
95
|
-
struct Gyro_Timer *timer;
|
96
|
-
GetGyro_Timer(self, timer);
|
97
|
-
|
98
|
-
if (timer->active) {
|
99
|
-
timer->active = 0;
|
100
|
-
timer->fiber = Qnil;
|
101
|
-
timer->selector = Qnil;
|
102
|
-
ev_timer_stop(timer->ev_loop, &timer->ev_timer);
|
103
|
-
timer->ev_loop = 0;
|
104
|
-
}
|
105
|
-
|
106
|
-
return self;
|
107
|
-
}
|
108
|
-
|
109
|
-
VALUE Gyro_Timer_await(VALUE self) {
|
110
|
-
struct Gyro_Timer *timer;
|
111
|
-
VALUE ret;
|
112
|
-
|
113
|
-
GetGyro_Timer(self, timer);
|
114
|
-
|
115
|
-
timer->fiber = rb_fiber_current();
|
116
|
-
timer->selector = Thread_current_event_selector();
|
117
|
-
timer->ev_loop = Gyro_Selector_ev_loop(timer->selector);
|
118
|
-
|
119
|
-
if (timer->active != 1) {
|
120
|
-
timer->active = 1;
|
121
|
-
ev_timer_start(timer->ev_loop, &timer->ev_timer);
|
122
|
-
}
|
123
|
-
|
124
|
-
ret = Fiber_await();
|
125
|
-
RB_GC_GUARD(ret);
|
126
|
-
|
127
|
-
if (timer->active && (timer->repeat == .0)) {
|
128
|
-
timer->active = 0;
|
129
|
-
timer->fiber = Qnil;
|
130
|
-
timer->selector = Qnil;
|
131
|
-
ev_timer_stop(timer->ev_loop, &timer->ev_timer);
|
132
|
-
timer->ev_loop = 0;
|
133
|
-
}
|
134
|
-
|
135
|
-
// fiber is resumed, check if resumed value is an exception
|
136
|
-
timer->fiber = Qnil;
|
137
|
-
timer->selector = Qnil;
|
138
|
-
|
139
|
-
RB_GC_GUARD(self);
|
140
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
141
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
142
|
-
}
|
143
|
-
else
|
144
|
-
return ret;
|
145
|
-
}
|
146
|
-
|
147
|
-
void Init_Gyro_Timer() {
|
148
|
-
cGyro_Timer = rb_define_class_under(mGyro, "Timer", rb_cData);
|
149
|
-
rb_define_alloc_func(cGyro_Timer, Gyro_Timer_allocate);
|
150
|
-
|
151
|
-
rb_define_method(cGyro_Timer, "initialize", Gyro_Timer_initialize, 2);
|
152
|
-
rb_define_method(cGyro_Timer, "stop", Gyro_Timer_stop, 0);
|
153
|
-
rb_define_method(cGyro_Timer, "await", Gyro_Timer_await, 0);
|
154
|
-
}
|