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/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() {
|