polyphony 0.39 → 0.40
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.
- 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
|