polyphony 0.39 → 0.40
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -2
- data/Gemfile.lock +3 -3
- data/README.md +2 -1
- data/examples/io/tunnel.rb +48 -0
- data/ext/gyro/async.c +15 -45
- data/ext/gyro/child.c +8 -41
- data/ext/gyro/fiber.c +4 -3
- data/ext/gyro/gyro.c +12 -17
- data/ext/gyro/gyro.h +48 -0
- data/ext/gyro/io.c +13 -45
- data/ext/gyro/queue.c +31 -27
- data/ext/gyro/selector.c +0 -23
- data/ext/gyro/signal.c +8 -42
- data/ext/gyro/socket.c +7 -4
- data/ext/gyro/thread.c +27 -18
- data/ext/gyro/timer.c +18 -54
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +1 -3
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +3 -10
- data/test/test_async.rb +2 -0
- data/test/test_global_api.rb +9 -9
- data/test/test_io.rb +0 -7
- data/test/test_thread.rb +1 -1
- data/test/test_thread_pool.rb +2 -2
- data/test/test_throttler.rb +5 -3
- data/test/test_timer.rb +24 -0
- metadata +5 -4
data/ext/gyro/queue.c
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
#include "gyro.h"
|
2
2
|
|
3
|
-
struct
|
3
|
+
typedef struct queue {
|
4
4
|
VALUE items;
|
5
5
|
VALUE shift_waiters;
|
6
|
-
};
|
6
|
+
} Gyro_Queue_t;
|
7
7
|
|
8
8
|
VALUE cGyro_Queue = Qnil;
|
9
9
|
|
10
10
|
static void Gyro_Queue_mark(void *ptr) {
|
11
|
-
|
11
|
+
Gyro_Queue_t *queue = ptr;
|
12
12
|
if (queue->items != Qnil) {
|
13
13
|
rb_gc_mark(queue->items);
|
14
14
|
}
|
@@ -17,59 +17,60 @@ static void Gyro_Queue_mark(void *ptr) {
|
|
17
17
|
}
|
18
18
|
}
|
19
19
|
|
20
|
-
static void Gyro_Queue_free(void *ptr) {
|
21
|
-
struct Gyro_Queue *queue = ptr;
|
22
|
-
xfree(queue);
|
23
|
-
}
|
24
|
-
|
25
20
|
static size_t Gyro_Queue_size(const void *ptr) {
|
26
|
-
return sizeof(
|
21
|
+
return sizeof(Gyro_Queue_t);
|
27
22
|
}
|
28
23
|
|
29
24
|
static const rb_data_type_t Gyro_Queue_type = {
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
"Gyro_Queue",
|
26
|
+
{Gyro_Queue_mark, RUBY_DEFAULT_FREE, Gyro_Queue_size,},
|
27
|
+
0, 0, 0
|
33
28
|
};
|
34
29
|
|
35
30
|
static VALUE Gyro_Queue_allocate(VALUE klass) {
|
36
|
-
|
31
|
+
Gyro_Queue_t *queue;
|
32
|
+
// return Data_Make_Struct(klass, Gyro_Queue_t, Gyro_Queue_mark, free, queue);
|
33
|
+
|
34
|
+
queue = ALLOC(Gyro_Queue_t);
|
35
|
+
// struct Gyro_Queue *queue = ALLOC(struct Gyro_Queue);
|
37
36
|
return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
|
38
37
|
}
|
38
|
+
|
39
39
|
#define GetGyro_Queue(obj, queue) \
|
40
|
-
TypedData_Get_Struct((obj),
|
40
|
+
TypedData_Get_Struct((obj), Gyro_Queue_t, &Gyro_Queue_type, (queue))
|
41
41
|
|
42
42
|
static VALUE Gyro_Queue_initialize(VALUE self) {
|
43
|
-
|
43
|
+
Gyro_Queue_t *queue;
|
44
44
|
GetGyro_Queue(self, queue);
|
45
45
|
|
46
46
|
queue->items = rb_ary_new();
|
47
47
|
queue->shift_waiters = rb_ary_new();
|
48
|
-
|
48
|
+
|
49
49
|
return self;
|
50
50
|
}
|
51
51
|
|
52
52
|
VALUE Gyro_Queue_push(VALUE self, VALUE value) {
|
53
|
-
|
53
|
+
Gyro_Queue_t *queue;
|
54
54
|
GetGyro_Queue(self, queue);
|
55
55
|
|
56
56
|
if (RARRAY_LEN(queue->shift_waiters) > 0) {
|
57
57
|
VALUE async = rb_ary_shift(queue->shift_waiters);
|
58
58
|
rb_funcall(async, ID_signal, 1, Qnil);
|
59
59
|
}
|
60
|
-
|
60
|
+
|
61
61
|
rb_ary_push(queue->items, value);
|
62
62
|
return self;
|
63
63
|
}
|
64
64
|
|
65
65
|
VALUE Gyro_Queue_shift(VALUE self) {
|
66
|
-
|
66
|
+
Gyro_Queue_t *queue;
|
67
67
|
GetGyro_Queue(self, queue);
|
68
68
|
|
69
69
|
if (RARRAY_LEN(queue->items) == 0) {
|
70
|
+
VALUE ret;
|
70
71
|
VALUE async = Fiber_auto_async(rb_fiber_current());
|
71
72
|
rb_ary_push(queue->shift_waiters, async);
|
72
|
-
|
73
|
+
ret = Gyro_Async_await_no_raise(async);
|
73
74
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
74
75
|
rb_ary_delete(queue->shift_waiters, async);
|
75
76
|
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
@@ -81,17 +82,17 @@ VALUE Gyro_Queue_shift(VALUE self) {
|
|
81
82
|
}
|
82
83
|
|
83
84
|
VALUE Gyro_Queue_shift_no_wait(VALUE self) {
|
84
|
-
|
85
|
+
Gyro_Queue_t *queue;
|
85
86
|
GetGyro_Queue(self, queue);
|
86
87
|
|
87
88
|
return rb_ary_shift(queue->items);
|
88
89
|
}
|
89
90
|
|
90
91
|
VALUE Gyro_Queue_shift_each(VALUE self) {
|
91
|
-
|
92
|
+
Gyro_Queue_t *queue;
|
93
|
+
VALUE old_queue;
|
92
94
|
GetGyro_Queue(self, queue);
|
93
|
-
|
94
|
-
VALUE old_queue = queue->items;
|
95
|
+
old_queue = queue->items;
|
95
96
|
queue->items = rb_ary_new();
|
96
97
|
|
97
98
|
if (rb_block_given_p()) {
|
@@ -104,12 +105,13 @@ VALUE Gyro_Queue_shift_each(VALUE self) {
|
|
104
105
|
return self;
|
105
106
|
}
|
106
107
|
else {
|
108
|
+
RB_GC_GUARD(old_queue);
|
107
109
|
return old_queue;
|
108
110
|
}
|
109
111
|
}
|
110
112
|
|
111
113
|
VALUE Gyro_Queue_clear(VALUE self) {
|
112
|
-
|
114
|
+
Gyro_Queue_t *queue;
|
113
115
|
GetGyro_Queue(self, queue);
|
114
116
|
|
115
117
|
rb_ary_clear(queue->items);
|
@@ -117,7 +119,7 @@ VALUE Gyro_Queue_clear(VALUE self) {
|
|
117
119
|
}
|
118
120
|
|
119
121
|
VALUE Gyro_Queue_empty_p(VALUE self) {
|
120
|
-
|
122
|
+
Gyro_Queue_t *queue;
|
121
123
|
GetGyro_Queue(self, queue);
|
122
124
|
|
123
125
|
return (RARRAY_LEN(queue->items) == 0) ? Qtrue : Qfalse;
|
@@ -133,10 +135,12 @@ void Init_Gyro_Queue() {
|
|
133
135
|
|
134
136
|
rb_define_method(cGyro_Queue, "pop", Gyro_Queue_shift, 0);
|
135
137
|
rb_define_method(cGyro_Queue, "shift", Gyro_Queue_shift, 0);
|
136
|
-
|
138
|
+
|
137
139
|
rb_define_method(cGyro_Queue, "shift_no_wait", Gyro_Queue_shift_no_wait, 0);
|
138
140
|
|
139
141
|
rb_define_method(cGyro_Queue, "shift_each", Gyro_Queue_shift_each, 0);
|
140
142
|
rb_define_method(cGyro_Queue, "clear", Gyro_Queue_clear, 0);
|
141
143
|
rb_define_method(cGyro_Queue, "empty?", Gyro_Queue_empty_p, 0);
|
142
144
|
}
|
145
|
+
|
146
|
+
|
data/ext/gyro/selector.c
CHANGED
@@ -174,26 +174,6 @@ VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self) {
|
|
174
174
|
return Qnil;
|
175
175
|
}
|
176
176
|
|
177
|
-
ID ID_deactivate_post_fork;
|
178
|
-
|
179
|
-
static int deactivate_watcher(VALUE key, VALUE value, VALUE _) {
|
180
|
-
rb_funcall(key, ID_deactivate_post_fork, 0);
|
181
|
-
return ST_CONTINUE;
|
182
|
-
}
|
183
|
-
|
184
|
-
VALUE Gyro_Selector_deactivate_all_watchers_post_fork(VALUE self) {
|
185
|
-
struct Gyro_Selector *selector;
|
186
|
-
GetGyro_Selector(self, selector);
|
187
|
-
|
188
|
-
VALUE old_active_watchers = selector->active_watchers;
|
189
|
-
selector->active_watchers = rb_hash_new();
|
190
|
-
|
191
|
-
rb_hash_foreach(old_active_watchers, deactivate_watcher, Qnil);
|
192
|
-
|
193
|
-
RB_GC_GUARD(old_active_watchers);
|
194
|
-
return self;
|
195
|
-
}
|
196
|
-
|
197
177
|
inline static VALUE Gyro_Selector_wait_readable(VALUE self, VALUE io) {
|
198
178
|
VALUE watcher = IO_read_watcher(io);
|
199
179
|
return Gyro_IO_await(watcher);
|
@@ -222,7 +202,4 @@ void Init_Gyro_Selector() {
|
|
222
202
|
rb_define_method(cGyro_Selector, "wait_writable", Gyro_Selector_wait_writable, 1);
|
223
203
|
rb_define_method(cGyro_Selector, "wait_timeout", Gyro_Selector_wait_timeout, 1);
|
224
204
|
rb_define_method(cGyro_Selector, "break_out_of_ev_loop", Gyro_Selector_break_out_of_ev_loop, 0);
|
225
|
-
rb_define_method(cGyro_Selector, "deactivate_all_watchers_post_fork", Gyro_Selector_deactivate_all_watchers_post_fork, 0);
|
226
|
-
|
227
|
-
ID_deactivate_post_fork = rb_intern("deactivate_post_fork");
|
228
205
|
}
|
data/ext/gyro/signal.c
CHANGED
@@ -1,38 +1,20 @@
|
|
1
1
|
#include "gyro.h"
|
2
2
|
|
3
3
|
struct Gyro_Signal {
|
4
|
-
|
5
|
-
|
6
|
-
int active;
|
7
|
-
int signum;
|
8
|
-
VALUE self;
|
9
|
-
VALUE fiber;
|
10
|
-
VALUE selector;
|
4
|
+
GYRO_WATCHER_DECL(ev_signal);
|
5
|
+
int signum;
|
11
6
|
};
|
12
7
|
|
13
8
|
static VALUE cGyro_Signal = Qnil;
|
14
9
|
|
15
10
|
static void Gyro_Signal_mark(void *ptr) {
|
16
11
|
struct Gyro_Signal *signal = ptr;
|
17
|
-
|
18
|
-
rb_gc_mark(signal->fiber);
|
19
|
-
}
|
20
|
-
if (signal->selector != Qnil) {
|
21
|
-
rb_gc_mark(signal->selector);
|
22
|
-
}
|
12
|
+
GYRO_WATCHER_MARK(signal);
|
23
13
|
}
|
24
14
|
|
25
15
|
static void Gyro_Signal_free(void *ptr) {
|
26
16
|
struct Gyro_Signal *signal = ptr;
|
27
|
-
|
28
|
-
case GYRO_WATCHER_POST_FORK:
|
29
|
-
return;
|
30
|
-
case 1:
|
31
|
-
ev_clear_pending(signal->ev_loop, &signal->ev_signal);
|
32
|
-
ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
33
|
-
default:
|
34
|
-
xfree(signal);
|
35
|
-
}
|
17
|
+
GYRO_WATCHER_FREE(signal);
|
36
18
|
}
|
37
19
|
|
38
20
|
static size_t Gyro_Signal_size(const void *ptr) {
|
@@ -85,16 +67,10 @@ void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal,
|
|
85
67
|
static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
86
68
|
struct Gyro_Signal *signal;
|
87
69
|
VALUE signum = sig;
|
88
|
-
|
70
|
+
|
89
71
|
GetGyro_Signal(self, signal);
|
90
|
-
|
91
|
-
signal->self = self;
|
92
|
-
signal->fiber = Qnil;
|
93
|
-
signal->selector = Qnil;
|
72
|
+
GYRO_WATCHER_INITIALIZE(signal, self);
|
94
73
|
signal->signum = NUM2INT(signum);
|
95
|
-
signal->active = 0;
|
96
|
-
signal->ev_loop = 0;
|
97
|
-
|
98
74
|
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
99
75
|
|
100
76
|
return Qnil;
|
@@ -102,10 +78,11 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
102
78
|
|
103
79
|
static VALUE Gyro_Signal_await(VALUE self) {
|
104
80
|
struct Gyro_Signal *signal;
|
81
|
+
VALUE ret;
|
105
82
|
GetGyro_Signal(self, signal);
|
106
83
|
|
107
84
|
signal_activate(signal);
|
108
|
-
|
85
|
+
ret = Gyro_switchpoint();
|
109
86
|
signal_deactivate(signal);
|
110
87
|
|
111
88
|
TEST_RESUME_EXCEPTION(ret);
|
@@ -113,21 +90,10 @@ static VALUE Gyro_Signal_await(VALUE self) {
|
|
113
90
|
return ret;
|
114
91
|
}
|
115
92
|
|
116
|
-
VALUE Gyro_Signal_deactivate_post_fork(VALUE self) {
|
117
|
-
struct Gyro_Signal *signal;
|
118
|
-
GetGyro_Signal(self, signal);
|
119
|
-
|
120
|
-
if (signal->active)
|
121
|
-
signal->active = GYRO_WATCHER_POST_FORK;
|
122
|
-
|
123
|
-
return self;
|
124
|
-
}
|
125
|
-
|
126
93
|
void Init_Gyro_Signal() {
|
127
94
|
cGyro_Signal = rb_define_class_under(mGyro, "Signal", rb_cData);
|
128
95
|
rb_define_alloc_func(cGyro_Signal, Gyro_Signal_allocate);
|
129
96
|
|
130
97
|
rb_define_method(cGyro_Signal, "initialize", Gyro_Signal_initialize, 1);
|
131
98
|
rb_define_method(cGyro_Signal, "await", Gyro_Signal_await, 0);
|
132
|
-
rb_define_method(cGyro_Signal, "deactivate_post_fork", Gyro_Signal_deactivate_post_fork, 0);
|
133
99
|
}
|
data/ext/gyro/socket.c
CHANGED
@@ -72,7 +72,7 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
|
|
72
72
|
rb_blocking_function_t *func;
|
73
73
|
const char *funcname;
|
74
74
|
VALUE write_watcher = Qnil;
|
75
|
-
|
75
|
+
|
76
76
|
rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
|
77
77
|
|
78
78
|
StringValue(arg.mesg);
|
@@ -196,14 +196,17 @@ static VALUE Socket_accept(VALUE sock) {
|
|
196
196
|
}
|
197
197
|
|
198
198
|
void Init_Socket() {
|
199
|
+
VALUE cBasicSocket;
|
200
|
+
VALUE cSocket;
|
201
|
+
|
199
202
|
rb_require("socket");
|
200
|
-
|
203
|
+
cBasicSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
|
201
204
|
|
202
205
|
rb_define_method(cBasicSocket, "send", BasicSocket_send, -1);
|
203
206
|
rb_define_method(cBasicSocket, "recv", BasicSocket_recv, -1);
|
204
207
|
|
205
|
-
|
206
|
-
|
208
|
+
cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
|
209
|
+
|
207
210
|
rb_define_method(cSocket, "accept", Socket_accept, 0);
|
208
211
|
|
209
212
|
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
data/ext/gyro/thread.c
CHANGED
@@ -40,11 +40,14 @@ static VALUE Thread_create_event_selector(VALUE self, VALUE thread) {
|
|
40
40
|
}
|
41
41
|
|
42
42
|
static VALUE Thread_setup_fiber_scheduling(VALUE self) {
|
43
|
+
VALUE queue;
|
44
|
+
VALUE selector;
|
45
|
+
|
43
46
|
rb_ivar_set(self, ID_ivar_main_fiber, rb_fiber_current());
|
44
47
|
rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(0));
|
45
|
-
|
48
|
+
queue = rb_ary_new();
|
46
49
|
rb_ivar_set(self, ID_run_queue, queue);
|
47
|
-
|
50
|
+
selector = rb_funcall(rb_cThread, ID_create_event_selector, 1, self);
|
48
51
|
rb_ivar_set(self, ID_ivar_event_selector, selector);
|
49
52
|
|
50
53
|
return self;
|
@@ -101,20 +104,21 @@ static VALUE Thread_fiber_scheduling_stats(VALUE self) {
|
|
101
104
|
VALUE stats = rb_hash_new();
|
102
105
|
VALUE queue = rb_ivar_get(self, ID_run_queue);
|
103
106
|
VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
|
104
|
-
|
107
|
+
long pending_count;
|
108
|
+
|
105
109
|
long scheduled_count = RARRAY_LEN(queue);
|
106
110
|
rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
|
107
111
|
|
108
|
-
|
112
|
+
pending_count = Gyro_Selector_pending_count(selector);
|
109
113
|
rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
|
110
114
|
|
111
115
|
return stats;
|
112
116
|
}
|
113
117
|
|
114
118
|
VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
115
|
-
|
116
|
-
|
117
|
-
|
119
|
+
VALUE queue;
|
120
|
+
|
121
|
+
if (rb_fiber_alive_p(fiber) != Qtrue) return self;
|
118
122
|
|
119
123
|
FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
|
120
124
|
// if fiber is already scheduled, just set the scheduled value, then return
|
@@ -123,7 +127,7 @@ VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
|
123
127
|
return self;
|
124
128
|
}
|
125
129
|
|
126
|
-
|
130
|
+
queue = rb_ivar_get(self, ID_run_queue);
|
127
131
|
rb_ary_push(queue, fiber);
|
128
132
|
rb_ivar_set(fiber, ID_runnable, Qtrue);
|
129
133
|
|
@@ -142,13 +146,14 @@ VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
|
|
142
146
|
}
|
143
147
|
|
144
148
|
VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value) {
|
145
|
-
|
146
|
-
|
147
|
-
|
149
|
+
VALUE queue;
|
150
|
+
|
151
|
+
if (rb_fiber_alive_p(fiber) != Qtrue) return self;
|
152
|
+
|
148
153
|
FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
|
149
154
|
rb_ivar_set(fiber, ID_runnable_value, value);
|
150
155
|
|
151
|
-
|
156
|
+
queue = rb_ivar_get(self, ID_run_queue);
|
152
157
|
|
153
158
|
// if fiber is already scheduled, remove it from the run queue
|
154
159
|
if (rb_ivar_get(fiber, ID_runnable) != Qnil) {
|
@@ -176,22 +181,25 @@ VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value)
|
|
176
181
|
|
177
182
|
VALUE Thread_switch_fiber(VALUE self) {
|
178
183
|
VALUE current_fiber = rb_fiber_current();
|
184
|
+
VALUE queue = rb_ivar_get(self, ID_run_queue);
|
185
|
+
VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
|
186
|
+
VALUE next_fiber;
|
187
|
+
VALUE value;
|
188
|
+
int ref_count;
|
189
|
+
|
179
190
|
if (__tracing_enabled__) {
|
180
191
|
if (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse) {
|
181
192
|
rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_switchpoint, current_fiber);
|
182
193
|
}
|
183
194
|
}
|
184
|
-
VALUE queue = rb_ivar_get(self, ID_run_queue);
|
185
|
-
VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
|
186
195
|
|
187
|
-
VALUE next_fiber;
|
188
196
|
|
189
197
|
while (1) {
|
190
198
|
next_fiber = rb_ary_shift(queue);
|
191
199
|
// if (break_flag != 0) {
|
192
200
|
// return Qnil;
|
193
201
|
// }
|
194
|
-
|
202
|
+
ref_count = Thread_fiber_ref_count(self);
|
195
203
|
if (next_fiber != Qnil) {
|
196
204
|
if (ref_count > 0) {
|
197
205
|
// this mechanism prevents event starvation in case the run queue never
|
@@ -212,7 +220,7 @@ VALUE Thread_switch_fiber(VALUE self) {
|
|
212
220
|
}
|
213
221
|
|
214
222
|
// run next fiber
|
215
|
-
|
223
|
+
value = rb_ivar_get(next_fiber, ID_runnable_value);
|
216
224
|
FIBER_TRACE(3, SYM_fiber_run, next_fiber, value);
|
217
225
|
|
218
226
|
rb_ivar_set(next_fiber, ID_runnable, Qnil);
|
@@ -236,9 +244,10 @@ VALUE Thread_post_fork(VALUE self) {
|
|
236
244
|
}
|
237
245
|
|
238
246
|
VALUE Gyro_switchpoint() {
|
247
|
+
VALUE ret;
|
239
248
|
VALUE thread = rb_thread_current();
|
240
249
|
Thread_ref(thread);
|
241
|
-
|
250
|
+
ret = Thread_switch_fiber(thread);
|
242
251
|
Thread_unref(thread);
|
243
252
|
RB_GC_GUARD(ret);
|
244
253
|
return ret;
|
data/ext/gyro/timer.c
CHANGED
@@ -1,39 +1,21 @@
|
|
1
1
|
#include "gyro.h"
|
2
2
|
|
3
3
|
struct Gyro_Timer {
|
4
|
-
|
5
|
-
struct ev_loop *ev_loop;
|
6
|
-
int active;
|
4
|
+
GYRO_WATCHER_DECL(ev_timer);
|
7
5
|
double after;
|
8
6
|
double repeat;
|
9
|
-
VALUE self;
|
10
|
-
VALUE fiber;
|
11
|
-
VALUE selector;
|
12
7
|
};
|
13
8
|
|
14
9
|
VALUE cGyro_Timer = Qnil;
|
15
10
|
|
16
11
|
static void Gyro_Timer_mark(void *ptr) {
|
17
12
|
struct Gyro_Timer *timer = ptr;
|
18
|
-
|
19
|
-
rb_gc_mark(timer->fiber);
|
20
|
-
}
|
21
|
-
if (timer->selector != Qnil) {
|
22
|
-
rb_gc_mark(timer->selector);
|
23
|
-
}
|
13
|
+
GYRO_WATCHER_MARK(timer);
|
24
14
|
}
|
25
15
|
|
26
16
|
static void Gyro_Timer_free(void *ptr) {
|
27
17
|
struct Gyro_Timer *timer = ptr;
|
28
|
-
|
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
|
-
}
|
18
|
+
GYRO_WATCHER_FREE(timer);
|
37
19
|
}
|
38
20
|
|
39
21
|
static size_t Gyro_Timer_size(const void *ptr) {
|
@@ -66,28 +48,26 @@ inline void timer_activate(struct Gyro_Timer *timer) {
|
|
66
48
|
ev_timer_start(timer->ev_loop, &timer->ev_timer);
|
67
49
|
}
|
68
50
|
|
69
|
-
inline void timer_deactivate(struct Gyro_Timer *timer, int
|
51
|
+
inline void timer_deactivate(struct Gyro_Timer *timer, int non_recurring_only) {
|
70
52
|
if (!timer->active) return;
|
71
53
|
|
72
|
-
timer->
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
timer->selector = Qnil;
|
54
|
+
if (!timer->repeat || !non_recurring_only) {
|
55
|
+
ev_timer_stop(timer->ev_loop, &timer->ev_timer);
|
56
|
+
if (RTEST(timer->selector)) {
|
57
|
+
Gyro_Selector_remove_active_watcher(timer->selector, timer->self);
|
58
|
+
timer->selector = Qnil;
|
59
|
+
}
|
60
|
+
timer->ev_loop = 0;
|
61
|
+
timer->active = 0;
|
81
62
|
}
|
82
|
-
|
83
|
-
timer->
|
63
|
+
|
64
|
+
timer->fiber = Qnil;
|
84
65
|
}
|
85
66
|
|
86
67
|
void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
|
87
68
|
struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
|
88
69
|
|
89
|
-
|
90
|
-
Fiber_make_runnable(timer->fiber, DBL2NUM(timer->after));
|
70
|
+
Fiber_make_runnable(timer->fiber, DBL2NUM(timer->after));
|
91
71
|
timer_deactivate(timer, 1);
|
92
72
|
}
|
93
73
|
|
@@ -95,15 +75,9 @@ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
|
|
95
75
|
struct Gyro_Timer *timer;
|
96
76
|
|
97
77
|
GetGyro_Timer(self, timer);
|
98
|
-
|
99
|
-
timer->self = self;
|
100
|
-
timer->fiber = Qnil;
|
101
|
-
timer->selector = Qnil;
|
78
|
+
GYRO_WATCHER_INITIALIZE(timer, self);
|
102
79
|
timer->after = NUM2DBL(after);
|
103
80
|
timer->repeat = NUM2DBL(repeat);
|
104
|
-
timer->active = 0;
|
105
|
-
timer->ev_loop = 0;
|
106
|
-
|
107
81
|
ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
|
108
82
|
|
109
83
|
return Qnil;
|
@@ -119,10 +93,11 @@ VALUE Gyro_Timer_stop(VALUE self) {
|
|
119
93
|
|
120
94
|
VALUE Gyro_Timer_await(VALUE self) {
|
121
95
|
struct Gyro_Timer *timer;
|
96
|
+
VALUE ret;
|
122
97
|
GetGyro_Timer(self, timer);
|
123
98
|
|
124
99
|
timer_activate(timer);
|
125
|
-
|
100
|
+
ret = Gyro_switchpoint();
|
126
101
|
timer_deactivate(timer, 1);
|
127
102
|
|
128
103
|
TEST_RESUME_EXCEPTION(ret);
|
@@ -130,22 +105,11 @@ VALUE Gyro_Timer_await(VALUE self) {
|
|
130
105
|
return ret;
|
131
106
|
}
|
132
107
|
|
133
|
-
VALUE Gyro_Timer_deactivate_post_fork(VALUE self) {
|
134
|
-
struct Gyro_Timer *timer;
|
135
|
-
GetGyro_Timer(self, timer);
|
136
|
-
|
137
|
-
if (timer->active)
|
138
|
-
timer->active = GYRO_WATCHER_POST_FORK;
|
139
|
-
|
140
|
-
return self;
|
141
|
-
}
|
142
|
-
|
143
108
|
void Init_Gyro_Timer() {
|
144
109
|
cGyro_Timer = rb_define_class_under(mGyro, "Timer", rb_cData);
|
145
110
|
rb_define_alloc_func(cGyro_Timer, Gyro_Timer_allocate);
|
146
111
|
|
147
112
|
rb_define_method(cGyro_Timer, "initialize", Gyro_Timer_initialize, 2);
|
148
113
|
rb_define_method(cGyro_Timer, "await", Gyro_Timer_await, 0);
|
149
|
-
rb_define_method(cGyro_Timer, "deactivate_post_fork", Gyro_Timer_deactivate_post_fork, 0);
|
150
114
|
rb_define_method(cGyro_Timer, "stop", Gyro_Timer_stop, 0);
|
151
115
|
}
|
data/lib/polyphony/version.rb
CHANGED
data/lib/polyphony.rb
CHANGED
@@ -14,7 +14,6 @@ require_relative './polyphony/extensions/io'
|
|
14
14
|
require_relative './polyphony/core/global_api'
|
15
15
|
require_relative './polyphony/core/resource_pool'
|
16
16
|
require_relative './polyphony/net'
|
17
|
-
|
18
17
|
require_relative './polyphony/adapters/process'
|
19
18
|
|
20
19
|
# Main Polyphony API
|
@@ -32,9 +31,8 @@ module Polyphony
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def fork(&block)
|
35
|
-
old_threads = Thread.list - [Thread.current]
|
36
34
|
Kernel.fork do
|
37
|
-
|
35
|
+
Gyro.incr_generation
|
38
36
|
|
39
37
|
# Since the fiber doing the fork will become the main fiber of the
|
40
38
|
# forked process, we leave it behind by transferring to a new fiber
|
data/polyphony.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency 'minitest-reporters', '1.4.2'
|
28
28
|
s.add_development_dependency 'simplecov', '0.17.1'
|
29
29
|
s.add_development_dependency 'rubocop', '0.80.0'
|
30
|
-
s.add_development_dependency 'pg', '1.1.
|
30
|
+
s.add_development_dependency 'pg', '1.1.4'
|
31
31
|
s.add_development_dependency 'rake-compiler', '1.0.5'
|
32
32
|
s.add_development_dependency 'redis', '4.1.0'
|
33
33
|
s.add_development_dependency 'hiredis', '0.6.3'
|
data/test/helper.rb
CHANGED
@@ -18,17 +18,9 @@ Minitest::Reporters.use! [
|
|
18
18
|
Minitest::Reporters::SpecReporter.new
|
19
19
|
]
|
20
20
|
|
21
|
-
module MiniTest::Assertions
|
22
|
-
def assert_in_range(range, act)
|
23
|
-
msg = message(msg) {
|
24
|
-
"Expected #{act.inspect} to be in range #{range.inspect}"
|
25
|
-
}
|
26
|
-
assert range.include?(act), msg
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
21
|
class MiniTest::Test
|
31
22
|
def setup
|
23
|
+
# puts "* setup #{self.name}"
|
32
24
|
if Fiber.current.children.size > 0
|
33
25
|
puts "Children left: #{Fiber.current.children.inspect}"
|
34
26
|
exit!
|
@@ -38,6 +30,7 @@ class MiniTest::Test
|
|
38
30
|
end
|
39
31
|
|
40
32
|
def teardown
|
33
|
+
#puts "* teardown #{self.name}"
|
41
34
|
Fiber.current.terminate_all_children
|
42
35
|
Fiber.current.await_all_children
|
43
36
|
end
|
@@ -49,4 +42,4 @@ module Kernel
|
|
49
42
|
rescue Exception => e
|
50
43
|
e
|
51
44
|
end
|
52
|
-
end
|
45
|
+
end
|
data/test/test_async.rb
CHANGED
@@ -22,6 +22,7 @@ class AsyncTest < MiniTest::Test
|
|
22
22
|
def test_that_async_watcher_coalesces_signals
|
23
23
|
count = 0
|
24
24
|
a = Gyro::Async.new
|
25
|
+
|
25
26
|
coproc = spin {
|
26
27
|
loop {
|
27
28
|
a.await
|
@@ -34,6 +35,7 @@ class AsyncTest < MiniTest::Test
|
|
34
35
|
orig_sleep 0.001
|
35
36
|
3.times { a.signal }
|
36
37
|
end
|
38
|
+
|
37
39
|
coproc.await
|
38
40
|
assert_equal 1, count
|
39
41
|
end
|