polyphony 0.34 → 0.36
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 +17 -0
- data/Gemfile.lock +1 -1
- data/TODO.md +7 -7
- 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 +8 -6
- data/docs/main-concepts/fiber-scheduling.md +55 -72
- data/examples/core/xx-timer-gc.rb +17 -0
- data/ext/gyro/async.c +48 -58
- data/ext/gyro/child.c +48 -38
- data/ext/gyro/fiber.c +113 -0
- data/ext/gyro/gyro.c +12 -106
- data/ext/gyro/gyro.h +54 -50
- data/ext/gyro/gyro_ext.c +2 -0
- data/ext/gyro/io.c +70 -43
- data/ext/gyro/queue.c +5 -5
- data/ext/gyro/selector.c +33 -11
- data/ext/gyro/signal.c +44 -34
- data/ext/gyro/socket.c +6 -7
- data/ext/gyro/thread.c +1 -1
- data/ext/gyro/timer.c +42 -62
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/extensions/fiber.rb +1 -1
- data/lib/polyphony/extensions/thread.rb +2 -2
- data/lib/polyphony/version.rb +1 -1
- data/test/test_async.rb +2 -2
- data/test/test_fiber.rb +4 -4
- data/test/test_global_api.rb +1 -1
- data/test/test_thread_pool.rb +1 -1
- metadata +9 -2
data/ext/gyro/gyro.c
CHANGED
@@ -6,47 +6,24 @@ ID ID_call;
|
|
6
6
|
ID ID_caller;
|
7
7
|
ID ID_clear;
|
8
8
|
ID ID_each;
|
9
|
-
ID
|
9
|
+
ID ID_empty;
|
10
10
|
ID ID_inspect;
|
11
11
|
ID ID_new;
|
12
|
+
ID ID_pop;
|
13
|
+
ID ID_push;
|
12
14
|
ID ID_raise;
|
13
15
|
ID ID_ivar_running;
|
14
16
|
ID ID_ivar_thread;
|
15
17
|
ID ID_runnable;
|
16
18
|
ID ID_runnable_value;
|
17
19
|
ID ID_size;
|
18
|
-
ID
|
20
|
+
ID ID_signal;
|
19
21
|
ID ID_switch_fiber;
|
20
22
|
ID ID_transfer;
|
21
23
|
ID ID_R;
|
22
24
|
ID ID_W;
|
23
25
|
ID ID_RW;
|
24
26
|
|
25
|
-
ID ID_trace_ev_loop_enter;
|
26
|
-
ID ID_trace_ev_loop_leave;
|
27
|
-
ID ID_trace_run;
|
28
|
-
ID ID_trace_runnable;
|
29
|
-
ID ID_trace_terminate;
|
30
|
-
ID ID_trace_wait;
|
31
|
-
|
32
|
-
ID ID_empty;
|
33
|
-
ID ID_pop;
|
34
|
-
ID ID_push;
|
35
|
-
|
36
|
-
VALUE SYM_dead;
|
37
|
-
VALUE SYM_running;
|
38
|
-
VALUE SYM_runnable;
|
39
|
-
VALUE SYM_waiting;
|
40
|
-
|
41
|
-
VALUE SYM_fiber_create;
|
42
|
-
VALUE SYM_fiber_ev_loop_enter;
|
43
|
-
VALUE SYM_fiber_ev_loop_leave;
|
44
|
-
VALUE SYM_fiber_run;
|
45
|
-
VALUE SYM_fiber_schedule;
|
46
|
-
VALUE SYM_fiber_switchpoint;
|
47
|
-
VALUE SYM_fiber_terminate;
|
48
|
-
|
49
|
-
|
50
27
|
static VALUE Gyro_break_set(VALUE self) {
|
51
28
|
// break_flag = 1;
|
52
29
|
ev_break(Gyro_Selector_current_thread_ev_loop(), EVBREAK_ALL);
|
@@ -59,13 +36,12 @@ static VALUE Gyro_break_set(VALUE self) {
|
|
59
36
|
|
60
37
|
VALUE Gyro_snooze(VALUE self) {
|
61
38
|
VALUE fiber = rb_fiber_current();
|
62
|
-
|
39
|
+
Fiber_make_runnable(fiber, Qnil);
|
63
40
|
|
64
41
|
VALUE ret = Thread_switch_fiber(rb_thread_current());
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
return ret;
|
42
|
+
TEST_RESUME_EXCEPTION(ret);
|
43
|
+
RB_GC_GUARD(ret);
|
44
|
+
return ret;
|
69
45
|
}
|
70
46
|
|
71
47
|
static VALUE Gyro_post_fork(VALUE self) {
|
@@ -84,46 +60,9 @@ static VALUE Gyro_unref(VALUE self) {
|
|
84
60
|
static VALUE Gyro_suspend(VALUE self) {
|
85
61
|
VALUE ret = Thread_switch_fiber(rb_thread_current());
|
86
62
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
else {
|
91
|
-
return ret;
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
96
|
-
VALUE arg = (argc == 0) ? Qnil : argv[0];
|
97
|
-
VALUE ret = rb_funcall(self, ID_transfer, 1, arg);
|
98
|
-
|
99
|
-
// fiber is resumed, check if resumed value is an exception
|
100
|
-
return RTEST(rb_obj_is_kind_of(ret, rb_eException)) ?
|
101
|
-
rb_funcall(rb_mKernel, ID_raise, 1, ret) : ret;
|
102
|
-
}
|
103
|
-
|
104
|
-
static VALUE Fiber_schedule(int argc, VALUE *argv, VALUE self) {
|
105
|
-
VALUE value = (argc == 0) ? Qnil : argv[0];
|
106
|
-
Gyro_schedule_fiber(self, value);
|
107
|
-
return self;
|
108
|
-
}
|
109
|
-
|
110
|
-
static VALUE Fiber_state(VALUE self) {
|
111
|
-
if (!rb_fiber_alive_p(self) || (rb_ivar_get(self, ID_ivar_running) == Qfalse))
|
112
|
-
return SYM_dead;
|
113
|
-
if (rb_fiber_current() == self) return SYM_running;
|
114
|
-
if (rb_ivar_get(self, ID_runnable) != Qnil) return SYM_runnable;
|
115
|
-
|
116
|
-
return SYM_waiting;
|
117
|
-
}
|
118
|
-
|
119
|
-
void Gyro_schedule_fiber(VALUE fiber, VALUE value) {
|
120
|
-
VALUE thread = rb_ivar_get(fiber, ID_ivar_thread);
|
121
|
-
if (thread != Qnil) {
|
122
|
-
Thread_schedule_fiber(thread, fiber, value);
|
123
|
-
}
|
124
|
-
else {
|
125
|
-
rb_warn("No thread set for fiber");
|
126
|
-
}
|
63
|
+
TEST_RESUME_EXCEPTION(ret);
|
64
|
+
RB_GC_GUARD(ret);
|
65
|
+
return ret;
|
127
66
|
}
|
128
67
|
|
129
68
|
VALUE Gyro_trace(VALUE self, VALUE enabled) {
|
@@ -145,11 +84,6 @@ void Init_Gyro() {
|
|
145
84
|
rb_define_global_function("snooze", Gyro_snooze, 0);
|
146
85
|
rb_define_global_function("suspend", Gyro_suspend, 0);
|
147
86
|
|
148
|
-
VALUE cFiber = rb_const_get(rb_cObject, rb_intern("Fiber"));
|
149
|
-
rb_define_method(cFiber, "safe_transfer", Fiber_safe_transfer, -1);
|
150
|
-
rb_define_method(cFiber, "schedule", Fiber_schedule, -1);
|
151
|
-
rb_define_method(cFiber, "state", Fiber_state, 0);
|
152
|
-
|
153
87
|
ID_call = rb_intern("call");
|
154
88
|
ID_caller = rb_intern("caller");
|
155
89
|
ID_clear = rb_intern("clear");
|
@@ -164,7 +98,7 @@ void Init_Gyro() {
|
|
164
98
|
ID_raise = rb_intern("raise");
|
165
99
|
ID_runnable = rb_intern("runnable");
|
166
100
|
ID_runnable_value = rb_intern("runnable_value");
|
167
|
-
|
101
|
+
ID_signal = rb_intern("signal");
|
168
102
|
ID_size = rb_intern("size");
|
169
103
|
ID_switch_fiber = rb_intern("switch_fiber");
|
170
104
|
ID_transfer = rb_intern("transfer");
|
@@ -172,32 +106,4 @@ void Init_Gyro() {
|
|
172
106
|
ID_R = rb_intern("r");
|
173
107
|
ID_RW = rb_intern("rw");
|
174
108
|
ID_W = rb_intern("w");
|
175
|
-
|
176
|
-
ID_fiber_trace = rb_intern("__fiber_trace__");
|
177
|
-
|
178
|
-
#define GLOBAL_SYM(sym) var = ID2SYM(rb_intern(sym)); rb_global_variable(sym)
|
179
|
-
|
180
|
-
SYM_dead = ID2SYM(rb_intern("dead"));
|
181
|
-
SYM_running = ID2SYM(rb_intern("running"));
|
182
|
-
SYM_runnable = ID2SYM(rb_intern("runnable"));
|
183
|
-
SYM_waiting = ID2SYM(rb_intern("waiting"));
|
184
|
-
rb_global_variable(&SYM_dead);
|
185
|
-
rb_global_variable(&SYM_running);
|
186
|
-
rb_global_variable(&SYM_runnable);
|
187
|
-
rb_global_variable(&SYM_waiting);
|
188
|
-
|
189
|
-
SYM_fiber_create = ID2SYM(rb_intern("fiber_create"));
|
190
|
-
SYM_fiber_ev_loop_enter = ID2SYM(rb_intern("fiber_ev_loop_enter"));
|
191
|
-
SYM_fiber_ev_loop_leave = ID2SYM(rb_intern("fiber_ev_loop_leave"));
|
192
|
-
SYM_fiber_run = ID2SYM(rb_intern("fiber_run"));
|
193
|
-
SYM_fiber_schedule = ID2SYM(rb_intern("fiber_schedule"));
|
194
|
-
SYM_fiber_switchpoint = ID2SYM(rb_intern("fiber_switchpoint"));
|
195
|
-
SYM_fiber_terminate = ID2SYM(rb_intern("fiber_terminate"));
|
196
|
-
rb_global_variable(&SYM_fiber_create);
|
197
|
-
rb_global_variable(&SYM_fiber_ev_loop_enter);
|
198
|
-
rb_global_variable(&SYM_fiber_ev_loop_leave);
|
199
|
-
rb_global_variable(&SYM_fiber_run);
|
200
|
-
rb_global_variable(&SYM_fiber_schedule);
|
201
|
-
rb_global_variable(&SYM_fiber_switchpoint);
|
202
|
-
rb_global_variable(&SYM_fiber_terminate);
|
203
109
|
}
|
data/ext/gyro/gyro.h
CHANGED
@@ -5,61 +5,17 @@
|
|
5
5
|
#include "ruby/io.h"
|
6
6
|
#include "libev.h"
|
7
7
|
|
8
|
-
|
9
|
-
FIBER_STATE_NOT_SCHEDULED = 0,
|
10
|
-
FIBER_STATE_WAITING = 1,
|
11
|
-
FIBER_STATE_SCHEDULED = 2
|
12
|
-
};
|
13
|
-
|
14
|
-
// void Gyro_add_watcher_ref(VALUE obj);
|
15
|
-
// void Gyro_del_watcher_ref(VALUE obj);
|
16
|
-
VALUE Gyro_snooze(VALUE self);
|
17
|
-
|
18
|
-
void Gyro_schedule_fiber(VALUE fiber, VALUE value);
|
19
|
-
|
20
|
-
int Gyro_ref_count();
|
21
|
-
void Gyro_ref_count_incr();
|
22
|
-
void Gyro_ref_count_decr();
|
23
|
-
|
24
|
-
VALUE Gyro_Async_await(VALUE async);
|
25
|
-
VALUE Gyro_Async_await_no_raise(VALUE async);
|
26
|
-
|
27
|
-
VALUE IO_read_watcher(VALUE io);
|
28
|
-
VALUE IO_write_watcher(VALUE io);
|
29
|
-
VALUE Gyro_IO_await(VALUE self);
|
30
|
-
|
31
|
-
VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber);
|
32
|
-
void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runnable_count);
|
33
|
-
|
34
|
-
VALUE Gyro_Timer_await(VALUE self);
|
35
|
-
|
36
|
-
int io_setstrbuf(VALUE *str, long len);
|
37
|
-
void io_set_read_length(VALUE str, long n, int shrinkable);
|
38
|
-
VALUE io_enc_str(VALUE str, rb_io_t *fptr);
|
39
|
-
|
40
|
-
struct ev_loop *Gyro_Selector_ev_loop(VALUE selector);
|
41
|
-
ev_tstamp Gyro_Selector_now(VALUE selector);
|
42
|
-
struct ev_loop *Gyro_Selector_current_thread_ev_loop();
|
43
|
-
long Gyro_Selector_pending_count(VALUE self);
|
44
|
-
VALUE Gyro_Selector_post_fork(VALUE self);
|
45
|
-
|
46
|
-
VALUE Thread_current_event_selector();
|
47
|
-
VALUE Thread_ref(VALUE thread);
|
48
|
-
VALUE Thread_unref(VALUE thread);
|
49
|
-
VALUE Thread_switch_fiber(VALUE thread);
|
50
|
-
VALUE Fiber_await();
|
51
|
-
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
52
|
-
VALUE Thread_post_fork(VALUE thread);
|
53
|
-
VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self);
|
54
|
-
|
55
|
-
VALUE Gyro_Queue_push(VALUE self, VALUE value);
|
56
|
-
|
8
|
+
// debugging
|
57
9
|
#define OBJ_ID(obj) (NUM2LONG(rb_funcall(obj, rb_intern("object_id"), 0)))
|
58
10
|
#define INSPECT(...) (rb_funcall(rb_cObject, rb_intern("p"), __VA_ARGS__))
|
59
11
|
#define FIBER_TRACE(...) if (__tracing_enabled__) { \
|
60
12
|
rb_funcall(rb_cObject, ID_fiber_trace, __VA_ARGS__); \
|
61
13
|
}
|
62
14
|
|
15
|
+
#define TEST_RESUME_EXCEPTION(ret) if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) { \
|
16
|
+
return rb_funcall(rb_mKernel, ID_raise, 1, ret); \
|
17
|
+
}
|
18
|
+
|
63
19
|
extern VALUE mGyro;
|
64
20
|
extern VALUE cGyro_Async;
|
65
21
|
extern VALUE cGyro_IO;
|
@@ -79,7 +35,7 @@ extern ID ID_new;
|
|
79
35
|
extern ID ID_raise;
|
80
36
|
extern ID ID_runnable;
|
81
37
|
extern ID ID_runnable_value;
|
82
|
-
extern ID
|
38
|
+
extern ID ID_signal;
|
83
39
|
extern ID ID_size;
|
84
40
|
extern ID ID_switch_fiber;
|
85
41
|
extern ID ID_transfer;
|
@@ -97,4 +53,52 @@ extern VALUE SYM_fiber_terminate;
|
|
97
53
|
|
98
54
|
extern int __tracing_enabled__;
|
99
55
|
|
56
|
+
enum {
|
57
|
+
FIBER_STATE_NOT_SCHEDULED = 0,
|
58
|
+
FIBER_STATE_WAITING = 1,
|
59
|
+
FIBER_STATE_SCHEDULED = 2
|
60
|
+
};
|
61
|
+
|
62
|
+
VALUE Fiber_auto_async(VALUE self);
|
63
|
+
VALUE Fiber_auto_io(VALUE self);
|
64
|
+
void Fiber_make_runnable(VALUE fiber, VALUE value);
|
65
|
+
|
66
|
+
VALUE Gyro_Async_await(VALUE async);
|
67
|
+
VALUE Gyro_Async_await_no_raise(VALUE async);
|
68
|
+
|
69
|
+
VALUE Gyro_IO_auto_io(int fd, int events);
|
70
|
+
VALUE Gyro_IO_await(VALUE self);
|
71
|
+
|
72
|
+
void Gyro_Selector_add_active_watcher(VALUE self, VALUE watcher);
|
73
|
+
VALUE Gyro_Selector_break_out_of_ev_loop(VALUE self);
|
74
|
+
struct ev_loop *Gyro_Selector_current_thread_ev_loop();
|
75
|
+
struct ev_loop *Gyro_Selector_ev_loop(VALUE selector);
|
76
|
+
ev_tstamp Gyro_Selector_now(VALUE selector);
|
77
|
+
long Gyro_Selector_pending_count(VALUE self);
|
78
|
+
VALUE Gyro_Selector_post_fork(VALUE self);
|
79
|
+
void Gyro_Selector_remove_active_watcher(VALUE self, VALUE watcher);
|
80
|
+
VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber);
|
81
|
+
void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runnable_count);
|
82
|
+
VALUE Gyro_switchpoint();
|
83
|
+
|
84
|
+
|
85
|
+
VALUE Gyro_snooze(VALUE self);
|
86
|
+
VALUE Gyro_Timer_await(VALUE self);
|
87
|
+
|
88
|
+
VALUE IO_read_watcher(VALUE io);
|
89
|
+
VALUE IO_write_watcher(VALUE io);
|
90
|
+
|
91
|
+
VALUE Gyro_Queue_push(VALUE self, VALUE value);
|
92
|
+
|
93
|
+
VALUE Thread_current_event_selector();
|
94
|
+
VALUE Thread_post_fork(VALUE thread);
|
95
|
+
VALUE Thread_ref(VALUE thread);
|
96
|
+
VALUE Thread_schedule_fiber(VALUE thread, VALUE fiber, VALUE value);
|
97
|
+
VALUE Thread_switch_fiber(VALUE thread);
|
98
|
+
VALUE Thread_unref(VALUE thread);
|
99
|
+
|
100
|
+
int io_setstrbuf(VALUE *str, long len);
|
101
|
+
void io_set_read_length(VALUE str, long n, int shrinkable);
|
102
|
+
VALUE io_enc_str(VALUE str, rb_io_t *fptr);
|
103
|
+
|
100
104
|
#endif /* RUBY_EV_H */
|
data/ext/gyro/gyro_ext.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "gyro.h"
|
2
2
|
|
3
|
+
void Init_Fiber();
|
3
4
|
void Init_Gyro();
|
4
5
|
void Init_Gyro_Async();
|
5
6
|
void Init_Gyro_Child();
|
@@ -24,6 +25,7 @@ void Init_gyro_ext() {
|
|
24
25
|
Init_Gyro_Signal();
|
25
26
|
Init_Gyro_Timer();
|
26
27
|
|
28
|
+
Init_Fiber();
|
27
29
|
Init_Socket();
|
28
30
|
Init_Thread();
|
29
31
|
|
data/ext/gyro/io.c
CHANGED
@@ -10,8 +10,9 @@ struct Gyro_IO {
|
|
10
10
|
struct ev_io ev_io;
|
11
11
|
struct ev_loop *ev_loop;
|
12
12
|
int active;
|
13
|
-
|
13
|
+
VALUE self;
|
14
14
|
VALUE fiber;
|
15
|
+
VALUE selector;
|
15
16
|
};
|
16
17
|
|
17
18
|
VALUE cGyro_IO = Qnil;
|
@@ -26,12 +27,16 @@ static void Gyro_IO_mark(void *ptr) {
|
|
26
27
|
if (io->fiber != Qnil) {
|
27
28
|
rb_gc_mark(io->fiber);
|
28
29
|
}
|
30
|
+
if (io->selector != Qnil) {
|
31
|
+
rb_gc_mark(io->selector);
|
32
|
+
}
|
29
33
|
}
|
30
34
|
|
31
35
|
static void Gyro_IO_free(void *ptr) {
|
32
36
|
struct Gyro_IO *io = ptr;
|
33
37
|
if (io->active) {
|
34
|
-
|
38
|
+
ev_clear_pending(io->ev_loop, &io->ev_io);
|
39
|
+
ev_io_stop(io->ev_loop, &io->ev_io);
|
35
40
|
}
|
36
41
|
xfree(io);
|
37
42
|
}
|
@@ -43,30 +48,42 @@ static size_t Gyro_IO_size(const void *ptr) {
|
|
43
48
|
static const rb_data_type_t Gyro_IO_type = {
|
44
49
|
"Gyro_IO",
|
45
50
|
{Gyro_IO_mark, Gyro_IO_free, Gyro_IO_size,},
|
46
|
-
0, 0,
|
47
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
51
|
+
0, 0, 0
|
48
52
|
};
|
49
53
|
|
50
54
|
static VALUE Gyro_IO_allocate(VALUE klass) {
|
51
|
-
struct Gyro_IO *io = (struct Gyro_IO
|
55
|
+
struct Gyro_IO *io = ALLOC(struct Gyro_IO);
|
52
56
|
|
53
57
|
return TypedData_Wrap_Struct(klass, &Gyro_IO_type, io);
|
54
58
|
}
|
55
59
|
|
56
|
-
|
57
|
-
|
60
|
+
inline void Gyro_IO_activate(struct Gyro_IO *io) {
|
61
|
+
if (io->active) return;
|
58
62
|
|
59
|
-
|
60
|
-
|
63
|
+
io->active = 1;
|
64
|
+
io->fiber = rb_fiber_current();
|
65
|
+
io->selector = Thread_current_event_selector();
|
66
|
+
io->ev_loop = Gyro_Selector_ev_loop(io->selector);
|
67
|
+
Gyro_Selector_add_active_watcher(io->selector, io->self);
|
68
|
+
ev_io_start(io->ev_loop, &io->ev_io);
|
69
|
+
}
|
70
|
+
|
71
|
+
inline void Gyro_IO_deactivate(struct Gyro_IO *io) {
|
72
|
+
if (!io->active) return;
|
61
73
|
|
62
|
-
ev_io_stop(io->ev_loop, ev_io);
|
74
|
+
ev_io_stop(io->ev_loop, &io->ev_io);
|
75
|
+
Gyro_Selector_remove_active_watcher(io->selector, io->self);
|
63
76
|
io->active = 0;
|
77
|
+
io->ev_loop = 0;
|
78
|
+
io->selector = Qnil;
|
79
|
+
io->fiber = Qnil;
|
80
|
+
}
|
64
81
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
82
|
+
void Gyro_IO_callback(struct ev_loop *ev_loop, struct ev_io *ev_io, int revents) {
|
83
|
+
struct Gyro_IO *io = (struct Gyro_IO*)ev_io;
|
84
|
+
|
85
|
+
Fiber_make_runnable(io->fiber, Qnil);
|
86
|
+
Gyro_IO_deactivate(io);
|
70
87
|
}
|
71
88
|
|
72
89
|
static int Gyro_IO_symbol2event_mask(VALUE sym) {
|
@@ -92,51 +109,61 @@ static int Gyro_IO_symbol2event_mask(VALUE sym) {
|
|
92
109
|
|
93
110
|
#define GetGyro_IO(obj, io) TypedData_Get_Struct((obj), struct Gyro_IO, &Gyro_IO_type, (io))
|
94
111
|
|
112
|
+
static const char * S_IO = "IO";
|
113
|
+
static const char * S_to_io = "to_io";
|
114
|
+
|
95
115
|
static VALUE Gyro_IO_initialize(VALUE self, VALUE io_obj, VALUE event_mask) {
|
96
116
|
struct Gyro_IO *io;
|
97
117
|
rb_io_t *fptr;
|
98
118
|
|
99
119
|
GetGyro_IO(self, io);
|
100
120
|
|
101
|
-
io->
|
121
|
+
io->self = self;
|
102
122
|
io->fiber = Qnil;
|
123
|
+
io->selector = Qnil;
|
103
124
|
io->active = 0;
|
125
|
+
io->ev_loop = 0;
|
104
126
|
|
105
|
-
|
106
|
-
|
127
|
+
int fd;
|
128
|
+
if (NIL_P(io_obj)) {
|
129
|
+
fd = 0;
|
130
|
+
}
|
131
|
+
else {
|
132
|
+
GetOpenFile(rb_convert_type(io_obj, T_FILE, S_IO, S_to_io), fptr);
|
133
|
+
fd = FPTR_TO_FD(fptr);
|
134
|
+
}
|
135
|
+
int events = Gyro_IO_symbol2event_mask(event_mask);
|
136
|
+
|
137
|
+
ev_io_init(&io->ev_io, Gyro_IO_callback, fd, events);
|
107
138
|
|
108
139
|
return Qnil;
|
109
140
|
}
|
110
141
|
|
111
142
|
VALUE Gyro_IO_await(VALUE self) {
|
112
143
|
struct Gyro_IO *io;
|
113
|
-
VALUE ret;
|
114
|
-
|
115
144
|
GetGyro_IO(self, io);
|
116
145
|
|
117
|
-
io
|
118
|
-
|
119
|
-
io
|
120
|
-
ev_io_start(io->ev_loop, &io->ev_io);
|
146
|
+
Gyro_IO_activate(io);
|
147
|
+
VALUE ret = Gyro_switchpoint();
|
148
|
+
Gyro_IO_deactivate(io);
|
121
149
|
|
122
|
-
ret
|
150
|
+
TEST_RESUME_EXCEPTION(ret);
|
123
151
|
RB_GC_GUARD(ret);
|
152
|
+
return ret;
|
153
|
+
}
|
124
154
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
}
|
155
|
+
VALUE Gyro_IO_auto_io(int fd, int events) {
|
156
|
+
VALUE watcher = Fiber_auto_io(rb_fiber_current());
|
157
|
+
struct Gyro_IO *io;
|
158
|
+
GetGyro_IO(watcher, io);
|
130
159
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
else {
|
136
|
-
return Qnil;
|
137
|
-
}
|
160
|
+
ev_io_set(&io->ev_io, fd, events);
|
161
|
+
|
162
|
+
RB_GC_GUARD(watcher);
|
163
|
+
return watcher;
|
138
164
|
}
|
139
165
|
|
166
|
+
|
140
167
|
//////////////////////////////////////////////////////////////////////
|
141
168
|
//////////////////////////////////////////////////////////////////////
|
142
169
|
// the following is copied verbatim from the Ruby source code (io.c)
|
@@ -233,8 +260,8 @@ static VALUE IO_read(int argc, VALUE *argv, VALUE io) {
|
|
233
260
|
if (n < 0) {
|
234
261
|
int e = errno;
|
235
262
|
if ((e == EWOULDBLOCK || e == EAGAIN)) {
|
236
|
-
if (read_watcher
|
237
|
-
read_watcher =
|
263
|
+
if (NIL_P(read_watcher))
|
264
|
+
read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
|
238
265
|
Gyro_IO_await(read_watcher);
|
239
266
|
}
|
240
267
|
else
|
@@ -311,8 +338,8 @@ static VALUE IO_readpartial(int argc, VALUE *argv, VALUE io) {
|
|
311
338
|
if (n < 0) {
|
312
339
|
int e = errno;
|
313
340
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
314
|
-
if (read_watcher
|
315
|
-
read_watcher =
|
341
|
+
if (NIL_P(read_watcher))
|
342
|
+
read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
|
316
343
|
Gyro_IO_await(read_watcher);
|
317
344
|
}
|
318
345
|
else
|
@@ -367,8 +394,8 @@ static VALUE IO_write(int argc, VALUE *argv, VALUE io) {
|
|
367
394
|
if (n < 0) {
|
368
395
|
int e = errno;
|
369
396
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
370
|
-
if (write_watcher
|
371
|
-
write_watcher =
|
397
|
+
if (NIL_P(write_watcher))
|
398
|
+
write_watcher = Gyro_IO_auto_io(fptr->fd, EV_WRITE);
|
372
399
|
Gyro_IO_await(write_watcher);
|
373
400
|
}
|
374
401
|
else {
|