polyphony 0.34 → 0.36
Sign up to get free protection for your applications and to get access to all the features.
- 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 {
|