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/queue.c
CHANGED
@@ -29,12 +29,11 @@ static size_t Gyro_Queue_size(const void *ptr) {
|
|
29
29
|
static const rb_data_type_t Gyro_Queue_type = {
|
30
30
|
"Gyro_Queue",
|
31
31
|
{Gyro_Queue_mark, Gyro_Queue_free, Gyro_Queue_size,},
|
32
|
-
0, 0,
|
33
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
32
|
+
0, 0, 0
|
34
33
|
};
|
35
34
|
|
36
35
|
static VALUE Gyro_Queue_allocate(VALUE klass) {
|
37
|
-
struct Gyro_Queue *queue = (struct Gyro_Queue
|
36
|
+
struct Gyro_Queue *queue = ALLOC(struct Gyro_Queue);
|
38
37
|
return TypedData_Wrap_Struct(klass, &Gyro_Queue_type, queue);
|
39
38
|
}
|
40
39
|
#define GetGyro_Queue(obj, queue) \
|
@@ -56,7 +55,7 @@ VALUE Gyro_Queue_push(VALUE self, VALUE value) {
|
|
56
55
|
|
57
56
|
if (RARRAY_LEN(queue->wait_queue) > 0) {
|
58
57
|
VALUE async = rb_ary_shift(queue->wait_queue);
|
59
|
-
rb_funcall(async,
|
58
|
+
rb_funcall(async, ID_signal, 1, Qnil);
|
60
59
|
}
|
61
60
|
|
62
61
|
rb_ary_push(queue->queue, value);
|
@@ -68,13 +67,14 @@ VALUE Gyro_Queue_shift(VALUE self) {
|
|
68
67
|
GetGyro_Queue(self, queue);
|
69
68
|
|
70
69
|
if (RARRAY_LEN(queue->queue) == 0) {
|
71
|
-
VALUE async =
|
70
|
+
VALUE async = Fiber_auto_async(rb_fiber_current());
|
72
71
|
rb_ary_push(queue->wait_queue, async);
|
73
72
|
VALUE ret = Gyro_Async_await_no_raise(async);
|
74
73
|
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
75
74
|
rb_ary_delete(queue->wait_queue, async);
|
76
75
|
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
77
76
|
}
|
77
|
+
RB_GC_GUARD(ret);
|
78
78
|
}
|
79
79
|
|
80
80
|
return rb_ary_shift(queue->queue);
|
data/ext/gyro/selector.c
CHANGED
@@ -5,19 +5,20 @@ struct Gyro_Selector {
|
|
5
5
|
long run_no_wait_count;
|
6
6
|
int ev_loop_running;
|
7
7
|
struct ev_async async;
|
8
|
+
VALUE active_watchers;
|
8
9
|
};
|
9
10
|
|
10
11
|
VALUE cGyro_Selector = Qnil;
|
11
12
|
|
12
13
|
static void Gyro_Selector_mark(void *ptr) {
|
13
|
-
|
14
|
+
struct Gyro_Selector *selector = ptr;
|
15
|
+
rb_gc_mark(selector->active_watchers);
|
14
16
|
}
|
15
17
|
|
16
18
|
static void Gyro_Selector_free(void *ptr) {
|
17
19
|
struct Gyro_Selector *selector = ptr;
|
18
20
|
ev_async_stop(selector->ev_loop, &selector->async);
|
19
21
|
if (selector->ev_loop && !ev_is_default_loop(selector->ev_loop)) {
|
20
|
-
// printf("Selector garbage collected before being stopped!\n");
|
21
22
|
ev_loop_destroy(selector->ev_loop);
|
22
23
|
}
|
23
24
|
xfree(selector);
|
@@ -30,12 +31,11 @@ static size_t Gyro_Selector_size(const void *ptr) {
|
|
30
31
|
static const rb_data_type_t Gyro_Selector_type = {
|
31
32
|
"Gyro_Selector",
|
32
33
|
{Gyro_Selector_mark, Gyro_Selector_free, Gyro_Selector_size,},
|
33
|
-
0, 0,
|
34
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
34
|
+
0, 0, 0
|
35
35
|
};
|
36
36
|
|
37
37
|
static VALUE Gyro_Selector_allocate(VALUE klass) {
|
38
|
-
struct Gyro_Selector *selector = (struct Gyro_Selector
|
38
|
+
struct Gyro_Selector *selector = ALLOC(struct Gyro_Selector);
|
39
39
|
return TypedData_Wrap_Struct(klass, &Gyro_Selector_type, selector);
|
40
40
|
}
|
41
41
|
|
@@ -75,6 +75,12 @@ void dummy_async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, in
|
|
75
75
|
// up the event loop.
|
76
76
|
}
|
77
77
|
|
78
|
+
inline void Gyro_Selector_run_ev_loop(struct Gyro_Selector *selector, int flags) {
|
79
|
+
selector->ev_loop_running = 1;
|
80
|
+
ev_run(selector->ev_loop, flags);
|
81
|
+
selector->ev_loop_running = 0;
|
82
|
+
}
|
83
|
+
|
78
84
|
static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
|
79
85
|
struct Gyro_Selector *selector;
|
80
86
|
GetGyro_Selector(self, selector);
|
@@ -83,21 +89,35 @@ static VALUE Gyro_Selector_initialize(VALUE self, VALUE thread) {
|
|
83
89
|
selector->ev_loop = use_default_loop ? EV_DEFAULT : ev_loop_new(EVFLAG_NOSIGMASK);
|
84
90
|
selector->run_no_wait_count = 0;
|
85
91
|
|
92
|
+
selector->active_watchers = rb_hash_new();
|
93
|
+
|
86
94
|
ev_async_init(&selector->async, dummy_async_callback);
|
87
95
|
ev_async_start(selector->ev_loop, &selector->async);
|
88
|
-
|
96
|
+
Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
|
89
97
|
return Qnil;
|
90
98
|
}
|
91
99
|
|
100
|
+
inline void Gyro_Selector_add_active_watcher(VALUE self, VALUE watcher) {
|
101
|
+
struct Gyro_Selector *selector;
|
102
|
+
GetGyro_Selector(self, selector);
|
103
|
+
|
104
|
+
rb_hash_aset(selector->active_watchers, watcher, Qtrue);
|
105
|
+
}
|
106
|
+
|
107
|
+
inline void Gyro_Selector_remove_active_watcher(VALUE self, VALUE watcher) {
|
108
|
+
struct Gyro_Selector *selector;
|
109
|
+
GetGyro_Selector(self, selector);
|
110
|
+
|
111
|
+
rb_hash_delete(selector->active_watchers, watcher);
|
112
|
+
}
|
113
|
+
|
92
114
|
inline VALUE Gyro_Selector_run(VALUE self, VALUE current_fiber) {
|
93
115
|
struct Gyro_Selector *selector;
|
94
116
|
GetGyro_Selector(self, selector);
|
95
117
|
if (selector->ev_loop) {
|
96
118
|
selector->run_no_wait_count = 0;
|
97
119
|
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
98
|
-
selector
|
99
|
-
ev_run(selector->ev_loop, EVRUN_ONCE);
|
100
|
-
selector->ev_loop_running = 0;
|
120
|
+
Gyro_Selector_run_ev_loop(selector, EVRUN_ONCE);
|
101
121
|
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
102
122
|
}
|
103
123
|
return Qnil;
|
@@ -114,7 +134,7 @@ inline void Gyro_Selector_run_no_wait(VALUE self, VALUE current_fiber, long runn
|
|
114
134
|
|
115
135
|
selector->run_no_wait_count = 0;
|
116
136
|
FIBER_TRACE(2, SYM_fiber_ev_loop_enter, current_fiber);
|
117
|
-
|
137
|
+
Gyro_Selector_run_ev_loop(selector, EVRUN_NOWAIT);
|
118
138
|
FIBER_TRACE(2, SYM_fiber_ev_loop_leave, current_fiber);
|
119
139
|
}
|
120
140
|
|
@@ -166,7 +186,9 @@ inline static VALUE Gyro_Selector_wait_writable(VALUE self, VALUE io) {
|
|
166
186
|
|
167
187
|
inline static VALUE Gyro_Selector_wait_timeout(VALUE self, VALUE duration) {
|
168
188
|
VALUE watcher = rb_funcall(cGyro_Timer, ID_new, 2, duration, Qnil);
|
169
|
-
|
189
|
+
VALUE ret = Gyro_Timer_await(watcher);
|
190
|
+
RB_GC_GUARD(watcher);
|
191
|
+
return ret;
|
170
192
|
}
|
171
193
|
|
172
194
|
void Init_Gyro_Selector() {
|
data/ext/gyro/signal.c
CHANGED
@@ -5,7 +5,9 @@ struct Gyro_Signal {
|
|
5
5
|
struct ev_loop *ev_loop;
|
6
6
|
int active;
|
7
7
|
int signum;
|
8
|
+
VALUE self;
|
8
9
|
VALUE fiber;
|
10
|
+
VALUE selector;
|
9
11
|
};
|
10
12
|
|
11
13
|
static VALUE cGyro_Signal = Qnil;
|
@@ -15,13 +17,16 @@ static void Gyro_Signal_mark(void *ptr) {
|
|
15
17
|
if (signal->fiber != Qnil) {
|
16
18
|
rb_gc_mark(signal->fiber);
|
17
19
|
}
|
20
|
+
if (signal->selector != Qnil) {
|
21
|
+
rb_gc_mark(signal->selector);
|
22
|
+
}
|
18
23
|
}
|
19
24
|
|
20
25
|
static void Gyro_Signal_free(void *ptr) {
|
21
26
|
struct Gyro_Signal *signal = ptr;
|
22
27
|
if (signal->active) {
|
23
|
-
|
24
|
-
|
28
|
+
ev_clear_pending(signal->ev_loop, &signal->ev_signal);
|
29
|
+
ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
25
30
|
}
|
26
31
|
xfree(signal);
|
27
32
|
}
|
@@ -33,26 +38,41 @@ static size_t Gyro_Signal_size(const void *ptr) {
|
|
33
38
|
static const rb_data_type_t Gyro_Signal_type = {
|
34
39
|
"Gyro_Signal",
|
35
40
|
{Gyro_Signal_mark, Gyro_Signal_free, Gyro_Signal_size,},
|
36
|
-
0, 0,
|
37
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
41
|
+
0, 0, 0
|
38
42
|
};
|
39
43
|
|
40
44
|
static VALUE Gyro_Signal_allocate(VALUE klass) {
|
41
|
-
struct Gyro_Signal *signal = (struct Gyro_Signal
|
45
|
+
struct Gyro_Signal *signal = ALLOC(struct Gyro_Signal);
|
42
46
|
return TypedData_Wrap_Struct(klass, &Gyro_Signal_type, signal);
|
43
47
|
}
|
44
48
|
|
49
|
+
inline void Gyro_Signal_activate(struct Gyro_Signal *signal) {
|
50
|
+
if (signal->active) return;
|
51
|
+
|
52
|
+
signal->active = 1;
|
53
|
+
signal->fiber = rb_fiber_current();
|
54
|
+
signal->selector = Thread_current_event_selector();
|
55
|
+
signal->ev_loop = Gyro_Selector_ev_loop(signal->selector);
|
56
|
+
Gyro_Selector_add_active_watcher(signal->selector, signal->self);
|
57
|
+
ev_signal_start(signal->ev_loop, &signal->ev_signal);
|
58
|
+
}
|
59
|
+
|
60
|
+
inline void Gyro_Signal_deactivate(struct Gyro_Signal *signal) {
|
61
|
+
if (!signal->active) return;
|
62
|
+
|
63
|
+
ev_signal_stop(signal->ev_loop, &signal->ev_signal);
|
64
|
+
Gyro_Selector_remove_active_watcher(signal->selector, signal->self);
|
65
|
+
signal->active = 0;
|
66
|
+
signal->ev_loop = 0;
|
67
|
+
signal->selector = Qnil;
|
68
|
+
signal->fiber = Qnil;
|
69
|
+
}
|
70
|
+
|
45
71
|
void Gyro_Signal_callback(struct ev_loop *ev_loop, struct ev_signal *ev_signal, int revents) {
|
46
72
|
struct Gyro_Signal *signal = (struct Gyro_Signal*)ev_signal;
|
47
73
|
|
48
|
-
|
49
|
-
|
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
|
-
}
|
74
|
+
Fiber_make_runnable(signal->fiber, INT2NUM(signal->signum));
|
75
|
+
Gyro_Signal_deactivate(signal);
|
56
76
|
}
|
57
77
|
|
58
78
|
#define GetGyro_Signal(obj, signal) \
|
@@ -63,7 +83,13 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
63
83
|
VALUE signum = sig;
|
64
84
|
|
65
85
|
GetGyro_Signal(self, signal);
|
86
|
+
|
87
|
+
signal->self = self;
|
88
|
+
signal->fiber = Qnil;
|
89
|
+
signal->selector = Qnil;
|
66
90
|
signal->signum = NUM2INT(signum);
|
91
|
+
signal->active = 0;
|
92
|
+
signal->ev_loop = 0;
|
67
93
|
|
68
94
|
ev_signal_init(&signal->ev_signal, Gyro_Signal_callback, signal->signum);
|
69
95
|
|
@@ -72,31 +98,15 @@ static VALUE Gyro_Signal_initialize(VALUE self, VALUE sig) {
|
|
72
98
|
|
73
99
|
static VALUE Gyro_Signal_await(VALUE self) {
|
74
100
|
struct Gyro_Signal *signal;
|
75
|
-
VALUE ret;
|
76
|
-
|
77
101
|
GetGyro_Signal(self, signal);
|
78
102
|
|
79
|
-
signal
|
80
|
-
|
81
|
-
signal
|
82
|
-
ev_signal_start(signal->ev_loop, &signal->ev_signal);
|
103
|
+
Gyro_Signal_activate(signal);
|
104
|
+
VALUE ret = Gyro_switchpoint();
|
105
|
+
Gyro_Signal_deactivate(signal);
|
83
106
|
|
84
|
-
ret
|
107
|
+
TEST_RESUME_EXCEPTION(ret);
|
85
108
|
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;
|
109
|
+
return ret;
|
100
110
|
}
|
101
111
|
|
102
112
|
void Init_Gyro_Signal() {
|
data/ext/gyro/socket.c
CHANGED
@@ -94,9 +94,8 @@ static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
|
|
94
94
|
arg.fd = fptr->fd;
|
95
95
|
arg.flags = NUM2INT(flags);
|
96
96
|
while ((n = (ssize_t)func(&arg)) < 0) {
|
97
|
-
if (write_watcher
|
98
|
-
write_watcher =
|
99
|
-
}
|
97
|
+
if (NIL_P(write_watcher))
|
98
|
+
write_watcher = Gyro_IO_auto_io(fptr->fd, EV_WRITE);
|
100
99
|
Gyro_IO_await(write_watcher);
|
101
100
|
}
|
102
101
|
return SSIZET2NUM(n);
|
@@ -132,8 +131,8 @@ static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
|
|
132
131
|
if (n < 0) {
|
133
132
|
int e = errno;
|
134
133
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
135
|
-
if (read_watcher
|
136
|
-
read_watcher =
|
134
|
+
if (NIL_P(read_watcher))
|
135
|
+
read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
|
137
136
|
Gyro_IO_await(read_watcher);
|
138
137
|
}
|
139
138
|
else
|
@@ -169,8 +168,8 @@ static VALUE Socket_accept(VALUE sock) {
|
|
169
168
|
if (fd < 0) {
|
170
169
|
int e = errno;
|
171
170
|
if (e == EWOULDBLOCK || e == EAGAIN) {
|
172
|
-
if (read_watcher
|
173
|
-
read_watcher =
|
171
|
+
if (NIL_P(read_watcher))
|
172
|
+
read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
|
174
173
|
Gyro_IO_await(read_watcher);
|
175
174
|
}
|
176
175
|
else
|
data/ext/gyro/thread.c
CHANGED
data/ext/gyro/timer.c
CHANGED
@@ -6,7 +6,6 @@ struct Gyro_Timer {
|
|
6
6
|
int active;
|
7
7
|
double after;
|
8
8
|
double repeat;
|
9
|
-
int should_free;
|
10
9
|
VALUE self;
|
11
10
|
VALUE fiber;
|
12
11
|
VALUE selector;
|
@@ -27,11 +26,10 @@ static void Gyro_Timer_mark(void *ptr) {
|
|
27
26
|
static void Gyro_Timer_free(void *ptr) {
|
28
27
|
struct Gyro_Timer *timer = ptr;
|
29
28
|
if (timer->active) {
|
30
|
-
|
31
|
-
timer->
|
32
|
-
} else {
|
33
|
-
xfree(timer);
|
29
|
+
ev_clear_pending(timer->ev_loop, &timer->ev_timer);
|
30
|
+
ev_timer_stop(timer->ev_loop, &timer->ev_timer);
|
34
31
|
}
|
32
|
+
xfree(timer);
|
35
33
|
}
|
36
34
|
|
37
35
|
static size_t Gyro_Timer_size(const void *ptr) {
|
@@ -41,34 +39,50 @@ static size_t Gyro_Timer_size(const void *ptr) {
|
|
41
39
|
static const rb_data_type_t Gyro_Timer_type = {
|
42
40
|
"Gyro_Timer",
|
43
41
|
{Gyro_Timer_mark, Gyro_Timer_free, Gyro_Timer_size,},
|
44
|
-
0, 0,
|
45
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
42
|
+
0, 0, 0
|
46
43
|
};
|
47
44
|
|
48
45
|
static VALUE Gyro_Timer_allocate(VALUE klass) {
|
49
|
-
struct Gyro_Timer *timer = (struct Gyro_Timer
|
46
|
+
struct Gyro_Timer *timer = ALLOC(struct Gyro_Timer);
|
50
47
|
return TypedData_Wrap_Struct(klass, &Gyro_Timer_type, timer);
|
51
48
|
}
|
49
|
+
|
52
50
|
#define GetGyro_Timer(obj, timer) \
|
53
51
|
TypedData_Get_Struct((obj), struct Gyro_Timer, &Gyro_Timer_type, (timer))
|
54
52
|
|
55
|
-
void
|
56
|
-
|
53
|
+
inline void Gyro_Timer_activate(struct Gyro_Timer *timer) {
|
54
|
+
timer->fiber = rb_fiber_current();
|
55
|
+
timer->selector = Thread_current_event_selector();
|
56
|
+
timer->ev_loop = Gyro_Selector_ev_loop(timer->selector);
|
57
57
|
|
58
|
-
if (timer->
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
if (timer->active) return;
|
59
|
+
|
60
|
+
timer->active = 1;
|
61
|
+
Gyro_Selector_add_active_watcher(timer->selector, timer->self);
|
62
|
+
ev_timer_start(timer->ev_loop, &timer->ev_timer);
|
63
|
+
}
|
64
|
+
|
65
|
+
inline void Gyro_Timer_deactivate(struct Gyro_Timer *timer, int non_recurring_only) {
|
66
|
+
if (!timer->active) return;
|
63
67
|
|
64
|
-
if (!timer->repeat) {
|
68
|
+
if (!timer->repeat || !non_recurring_only) {
|
69
|
+
ev_timer_stop(timer->ev_loop, &timer->ev_timer);
|
70
|
+
if (RTEST(timer->selector)) {
|
71
|
+
Gyro_Selector_remove_active_watcher(timer->selector, timer->self);
|
72
|
+
timer->selector = Qnil;
|
73
|
+
}
|
74
|
+
timer->ev_loop = 0;
|
65
75
|
timer->active = 0;
|
66
|
-
timer->selector = Qnil;
|
67
76
|
}
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
78
|
+
timer->fiber = Qnil;
|
79
|
+
}
|
80
|
+
|
81
|
+
void Gyro_Timer_callback(struct ev_loop *ev_loop, struct ev_timer *ev_timer, int revents) {
|
82
|
+
struct Gyro_Timer *timer = (struct Gyro_Timer*)ev_timer;
|
83
|
+
|
84
|
+
Fiber_make_runnable(timer->fiber, DBL2NUM(timer->after));
|
85
|
+
Gyro_Timer_deactivate(timer, 1);
|
72
86
|
}
|
73
87
|
|
74
88
|
static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
|
@@ -78,15 +92,13 @@ static VALUE Gyro_Timer_initialize(VALUE self, VALUE after, VALUE repeat) {
|
|
78
92
|
|
79
93
|
timer->self = self;
|
80
94
|
timer->fiber = Qnil;
|
95
|
+
timer->selector = Qnil;
|
81
96
|
timer->after = NUM2DBL(after);
|
82
97
|
timer->repeat = NUM2DBL(repeat);
|
83
98
|
timer->active = 0;
|
84
|
-
|
85
|
-
timer->should_free = 0;
|
99
|
+
timer->ev_loop = 0;
|
86
100
|
|
87
101
|
ev_timer_init(&timer->ev_timer, Gyro_Timer_callback, timer->after, timer->repeat);
|
88
|
-
timer->ev_loop = 0;
|
89
|
-
timer->selector = Qnil;
|
90
102
|
|
91
103
|
return Qnil;
|
92
104
|
}
|
@@ -95,53 +107,21 @@ VALUE Gyro_Timer_stop(VALUE self) {
|
|
95
107
|
struct Gyro_Timer *timer;
|
96
108
|
GetGyro_Timer(self, timer);
|
97
109
|
|
98
|
-
|
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
|
-
|
110
|
+
Gyro_Timer_deactivate(timer, 0);
|
106
111
|
return self;
|
107
112
|
}
|
108
113
|
|
109
114
|
VALUE Gyro_Timer_await(VALUE self) {
|
110
115
|
struct Gyro_Timer *timer;
|
111
|
-
VALUE ret;
|
112
|
-
|
113
116
|
GetGyro_Timer(self, timer);
|
114
117
|
|
115
|
-
timer
|
116
|
-
|
117
|
-
timer
|
118
|
-
|
119
|
-
if (timer->active != 1) {
|
120
|
-
timer->active = 1;
|
121
|
-
ev_timer_start(timer->ev_loop, &timer->ev_timer);
|
122
|
-
}
|
118
|
+
Gyro_Timer_activate(timer);
|
119
|
+
VALUE ret = Gyro_switchpoint();
|
120
|
+
Gyro_Timer_deactivate(timer, 1);
|
123
121
|
|
124
|
-
ret
|
122
|
+
TEST_RESUME_EXCEPTION(ret);
|
125
123
|
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;
|
124
|
+
return ret;
|
145
125
|
}
|
146
126
|
|
147
127
|
void Init_Gyro_Timer() {
|