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
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
Exception.__disable_sanitized_backtrace__ = true
|
7
|
+
|
8
|
+
timers = 10.times.map do
|
9
|
+
spin do
|
10
|
+
t = Gyro::Timer.new(1, 1)
|
11
|
+
t.await
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
sleep 0.1
|
16
|
+
GC.start
|
17
|
+
sleep 0.1
|
data/ext/gyro/async.c
CHANGED
@@ -4,8 +4,10 @@ struct Gyro_Async {
|
|
4
4
|
struct ev_async ev_async;
|
5
5
|
struct ev_loop *ev_loop;
|
6
6
|
int active;
|
7
|
+
VALUE self;
|
7
8
|
VALUE fiber;
|
8
9
|
VALUE value;
|
10
|
+
VALUE selector;
|
9
11
|
};
|
10
12
|
|
11
13
|
VALUE cGyro_Async = Qnil;
|
@@ -18,12 +20,16 @@ static void Gyro_Async_mark(void *ptr) {
|
|
18
20
|
if (async->value != Qnil) {
|
19
21
|
rb_gc_mark(async->value);
|
20
22
|
}
|
23
|
+
if (async->selector != Qnil) {
|
24
|
+
rb_gc_mark(async->selector);
|
25
|
+
}
|
21
26
|
}
|
22
27
|
|
23
28
|
static void Gyro_Async_free(void *ptr) {
|
24
29
|
struct Gyro_Async *async = ptr;
|
25
30
|
if (async->active) {
|
26
|
-
|
31
|
+
ev_clear_pending(async->ev_loop, &async->ev_async);
|
32
|
+
ev_async_stop(async->ev_loop, &async->ev_async);
|
27
33
|
}
|
28
34
|
xfree(async);
|
29
35
|
}
|
@@ -35,26 +41,42 @@ static size_t Gyro_Async_size(const void *ptr) {
|
|
35
41
|
static const rb_data_type_t Gyro_Async_type = {
|
36
42
|
"Gyro_Async",
|
37
43
|
{Gyro_Async_mark, Gyro_Async_free, Gyro_Async_size,},
|
38
|
-
0, 0,
|
39
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
44
|
+
0, 0, 0
|
40
45
|
};
|
41
46
|
|
42
47
|
static VALUE Gyro_Async_allocate(VALUE klass) {
|
43
|
-
struct Gyro_Async *async = (struct Gyro_Async
|
48
|
+
struct Gyro_Async *async = ALLOC(struct Gyro_Async);
|
44
49
|
return TypedData_Wrap_Struct(klass, &Gyro_Async_type, async);
|
45
50
|
}
|
46
51
|
|
47
|
-
void
|
48
|
-
|
52
|
+
inline void Gyro_Async_activate(struct Gyro_Async *async) {
|
53
|
+
if (async->active) return;
|
49
54
|
|
50
|
-
|
55
|
+
async->active = 1;
|
56
|
+
async->fiber = rb_fiber_current();
|
57
|
+
async->selector = Thread_current_event_selector();
|
58
|
+
async->ev_loop = Gyro_Selector_ev_loop(async->selector);
|
59
|
+
Gyro_Selector_add_active_watcher(async->selector, async->self);
|
60
|
+
ev_async_start(async->ev_loop, &async->ev_async);
|
61
|
+
}
|
62
|
+
|
63
|
+
inline void Gyro_Async_deactivate(struct Gyro_Async *async) {
|
64
|
+
if (!async->active) return;
|
65
|
+
|
66
|
+
ev_async_stop(async->ev_loop, &async->ev_async);
|
67
|
+
Gyro_Selector_remove_active_watcher(async->selector, async->self);
|
51
68
|
async->active = 0;
|
69
|
+
async->ev_loop = 0;
|
70
|
+
async->selector = Qnil;
|
71
|
+
async->fiber = Qnil;
|
72
|
+
async->value = Qnil;
|
73
|
+
}
|
52
74
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
75
|
+
void Gyro_Async_callback(struct ev_loop *ev_loop, struct ev_async *ev_async, int revents) {
|
76
|
+
struct Gyro_Async *async = (struct Gyro_Async*)ev_async;
|
77
|
+
|
78
|
+
Fiber_make_runnable(async->fiber, async->value);
|
79
|
+
Gyro_Async_deactivate(async);
|
58
80
|
}
|
59
81
|
|
60
82
|
#define GetGyro_Async(obj, async) \
|
@@ -64,12 +86,14 @@ static VALUE Gyro_Async_initialize(VALUE self) {
|
|
64
86
|
struct Gyro_Async *async;
|
65
87
|
GetGyro_Async(self, async);
|
66
88
|
|
89
|
+
async->self = self;
|
67
90
|
async->fiber = Qnil;
|
68
91
|
async->value = Qnil;
|
92
|
+
async->selector = Qnil;
|
69
93
|
async->active = 0;
|
94
|
+
async->ev_loop = 0;
|
70
95
|
|
71
96
|
ev_async_init(&async->ev_async, Gyro_Async_callback);
|
72
|
-
async->ev_loop = 0;
|
73
97
|
|
74
98
|
return Qnil;
|
75
99
|
}
|
@@ -79,7 +103,7 @@ static VALUE Gyro_Async_signal(int argc, VALUE *argv, VALUE self) {
|
|
79
103
|
GetGyro_Async(self, async);
|
80
104
|
|
81
105
|
if (!async->active) {
|
82
|
-
// printf("signal
|
106
|
+
// printf("signal called before await\n");
|
83
107
|
return Qnil;
|
84
108
|
}
|
85
109
|
|
@@ -91,68 +115,34 @@ static VALUE Gyro_Async_signal(int argc, VALUE *argv, VALUE self) {
|
|
91
115
|
|
92
116
|
VALUE Gyro_Async_await(VALUE self) {
|
93
117
|
struct Gyro_Async *async;
|
94
|
-
VALUE ret;
|
95
|
-
|
96
118
|
GetGyro_Async(self, async);
|
97
119
|
|
98
|
-
async
|
99
|
-
|
100
|
-
|
101
|
-
async->ev_loop = Gyro_Selector_current_thread_ev_loop();
|
102
|
-
ev_async_start(async->ev_loop, &async->ev_async);
|
103
|
-
}
|
120
|
+
Gyro_Async_activate(async);
|
121
|
+
VALUE ret = Gyro_switchpoint();
|
122
|
+
Gyro_Async_deactivate(async);
|
104
123
|
|
105
|
-
ret
|
124
|
+
TEST_RESUME_EXCEPTION(ret);
|
106
125
|
RB_GC_GUARD(ret);
|
107
|
-
|
108
|
-
if (async->active) {
|
109
|
-
async->active = 0;
|
110
|
-
async->fiber = Qnil;
|
111
|
-
ev_async_stop(async->ev_loop, &async->ev_async);
|
112
|
-
async->value = Qnil;
|
113
|
-
}
|
114
|
-
|
115
|
-
// fiber is resumed
|
116
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
117
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
118
|
-
}
|
119
|
-
else {
|
120
|
-
return ret;
|
121
|
-
}
|
126
|
+
return ret;
|
122
127
|
}
|
123
128
|
|
124
129
|
VALUE Gyro_Async_await_no_raise(VALUE self) {
|
125
130
|
struct Gyro_Async *async;
|
126
|
-
VALUE ret;
|
127
|
-
|
128
131
|
GetGyro_Async(self, async);
|
129
132
|
|
130
|
-
async
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
ev_async_start(async->ev_loop, &async->ev_async);
|
135
|
-
}
|
136
|
-
|
137
|
-
ret = Fiber_await();
|
133
|
+
Gyro_Async_activate(async);
|
134
|
+
VALUE ret = Gyro_switchpoint();
|
135
|
+
Gyro_Async_deactivate(async);
|
136
|
+
|
138
137
|
RB_GC_GUARD(ret);
|
139
|
-
|
140
|
-
if (async->active) {
|
141
|
-
async->active = 0;
|
142
|
-
async->fiber = Qnil;
|
143
|
-
ev_async_stop(async->ev_loop, &async->ev_async);
|
144
|
-
async->value = Qnil;
|
145
|
-
}
|
146
|
-
|
147
138
|
return ret;
|
148
139
|
}
|
149
140
|
|
150
|
-
|
151
141
|
void Init_Gyro_Async() {
|
152
142
|
cGyro_Async = rb_define_class_under(mGyro, "Async", rb_cData);
|
153
143
|
rb_define_alloc_func(cGyro_Async, Gyro_Async_allocate);
|
154
144
|
|
155
145
|
rb_define_method(cGyro_Async, "initialize", Gyro_Async_initialize, 0);
|
156
|
-
rb_define_method(cGyro_Async, "signal
|
146
|
+
rb_define_method(cGyro_Async, "signal", Gyro_Async_signal, -1);
|
157
147
|
rb_define_method(cGyro_Async, "await", Gyro_Async_await, 0);
|
158
148
|
}
|
data/ext/gyro/child.c
CHANGED
@@ -7,6 +7,7 @@ struct Gyro_Child {
|
|
7
7
|
int pid;
|
8
8
|
VALUE self;
|
9
9
|
VALUE fiber;
|
10
|
+
VALUE selector;
|
10
11
|
};
|
11
12
|
|
12
13
|
static VALUE cGyro_Child = Qnil;
|
@@ -16,12 +17,16 @@ static void Gyro_Child_mark(void *ptr) {
|
|
16
17
|
if (child->fiber != Qnil) {
|
17
18
|
rb_gc_mark(child->fiber);
|
18
19
|
}
|
20
|
+
if (child->selector != Qnil) {
|
21
|
+
rb_gc_mark(child->selector);
|
22
|
+
}
|
19
23
|
}
|
20
24
|
|
21
25
|
static void Gyro_Child_free(void *ptr) {
|
22
26
|
struct Gyro_Child *child = ptr;
|
23
27
|
if (child->active) {
|
24
|
-
|
28
|
+
ev_clear_pending(child->ev_loop, &child->ev_child);
|
29
|
+
ev_child_stop(child->ev_loop, &child->ev_child);
|
25
30
|
}
|
26
31
|
xfree(child);
|
27
32
|
}
|
@@ -33,31 +38,51 @@ static size_t Gyro_Child_size(const void *ptr) {
|
|
33
38
|
static const rb_data_type_t Gyro_Child_type = {
|
34
39
|
"Gyro_Child",
|
35
40
|
{Gyro_Child_mark, Gyro_Child_free, Gyro_Child_size,},
|
36
|
-
0, 0,
|
37
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
41
|
+
0, 0, 0
|
38
42
|
};
|
39
43
|
|
40
44
|
static VALUE Gyro_Child_allocate(VALUE klass) {
|
41
|
-
struct Gyro_Child *child = (struct Gyro_Child
|
45
|
+
struct Gyro_Child *child = ALLOC(struct Gyro_Child);
|
42
46
|
return TypedData_Wrap_Struct(klass, &Gyro_Child_type, child);
|
43
47
|
}
|
44
48
|
|
49
|
+
inline void Gyro_Child_activate(struct Gyro_Child *child) {
|
50
|
+
if (child->active) return;
|
51
|
+
|
52
|
+
child->active = 1;
|
53
|
+
child->fiber = rb_fiber_current();
|
54
|
+
child->selector = Thread_current_event_selector();
|
55
|
+
child->ev_loop = Gyro_Selector_ev_loop(child->selector);
|
56
|
+
Gyro_Selector_add_active_watcher(child->selector, child->self);
|
57
|
+
ev_child_start(child->ev_loop, &child->ev_child);
|
58
|
+
}
|
59
|
+
|
60
|
+
inline void Gyro_Child_deactivate(struct Gyro_Child *child) {
|
61
|
+
if (!child->active) return;
|
62
|
+
|
63
|
+
ev_child_stop(child->ev_loop, &child->ev_child);
|
64
|
+
Gyro_Selector_remove_active_watcher(child->selector, child->self);
|
65
|
+
child->active = 0;
|
66
|
+
child->ev_loop = 0;
|
67
|
+
child->selector = Qnil;
|
68
|
+
child->fiber = Qnil;
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE Gyro_Child_resume_value(struct ev_child *ev_child) {
|
72
|
+
int exit_status = ev_child->rstatus >> 8; // weird, why should we do this?
|
73
|
+
|
74
|
+
return rb_ary_new_from_args(
|
75
|
+
2, INT2NUM(ev_child->rpid), INT2NUM(exit_status)
|
76
|
+
);
|
77
|
+
}
|
78
|
+
|
45
79
|
void Gyro_Child_callback(struct ev_loop *ev_loop, struct ev_child *ev_child, int revents) {
|
46
80
|
struct Gyro_Child *child = (struct Gyro_Child*)ev_child;
|
47
81
|
|
48
|
-
|
49
|
-
|
82
|
+
VALUE resume_value = Gyro_Child_resume_value(ev_child);
|
83
|
+
Fiber_make_runnable(child->fiber, resume_value);
|
50
84
|
|
51
|
-
|
52
|
-
VALUE fiber = child->fiber;
|
53
|
-
int exit_status = ev_child->rstatus >> 8; // weird, why should we do this?
|
54
|
-
|
55
|
-
VALUE resume_value = rb_ary_new_from_args(
|
56
|
-
2, INT2NUM(ev_child->rpid), INT2NUM(exit_status)
|
57
|
-
);
|
58
|
-
child->fiber = Qnil;
|
59
|
-
Gyro_schedule_fiber(fiber, resume_value);
|
60
|
-
}
|
85
|
+
Gyro_Child_deactivate(child);
|
61
86
|
}
|
62
87
|
|
63
88
|
#define GetGyro_Child(obj, child) \
|
@@ -70,8 +95,10 @@ static VALUE Gyro_Child_initialize(VALUE self, VALUE pid) {
|
|
70
95
|
|
71
96
|
child->self = self;
|
72
97
|
child->fiber = Qnil;
|
98
|
+
child->selector = Qnil;
|
73
99
|
child->pid = NUM2INT(pid);
|
74
100
|
child->active = 0;
|
101
|
+
child->ev_loop = 0;
|
75
102
|
|
76
103
|
ev_child_init(&child->ev_child, Gyro_Child_callback, child->pid, 0);
|
77
104
|
|
@@ -80,32 +107,15 @@ static VALUE Gyro_Child_initialize(VALUE self, VALUE pid) {
|
|
80
107
|
|
81
108
|
static VALUE Gyro_Child_await(VALUE self) {
|
82
109
|
struct Gyro_Child *child;
|
83
|
-
VALUE ret;
|
84
|
-
|
85
110
|
GetGyro_Child(self, child);
|
86
111
|
|
87
|
-
|
88
|
-
|
89
|
-
child
|
90
|
-
child->ev_loop = Gyro_Selector_current_thread_ev_loop();
|
91
|
-
ev_child_start(child->ev_loop, &child->ev_child);
|
112
|
+
Gyro_Child_activate(child);
|
113
|
+
VALUE ret = Gyro_switchpoint();
|
114
|
+
Gyro_Child_deactivate(child);
|
92
115
|
|
93
|
-
ret
|
116
|
+
TEST_RESUME_EXCEPTION(ret);
|
94
117
|
RB_GC_GUARD(ret);
|
95
|
-
|
96
|
-
if (child->active) {
|
97
|
-
child->active = 0;
|
98
|
-
child->fiber = Qnil;
|
99
|
-
ev_child_stop(child->ev_loop, &child->ev_child);
|
100
|
-
}
|
101
|
-
|
102
|
-
// fiber is resumed, check if resumed value is an exception
|
103
|
-
if (RTEST(rb_obj_is_kind_of(ret, rb_eException))) {
|
104
|
-
return rb_funcall(rb_mKernel, ID_raise, 1, ret);
|
105
|
-
}
|
106
|
-
else {
|
107
|
-
return ret;
|
108
|
-
}
|
118
|
+
return ret;
|
109
119
|
}
|
110
120
|
|
111
121
|
void Init_Gyro_Child() {
|
data/ext/gyro/fiber.c
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
#include "gyro.h"
|
2
|
+
|
3
|
+
ID ID_fiber_trace;
|
4
|
+
ID ID_ivar_auto_async;
|
5
|
+
ID ID_ivar_auto_io;
|
6
|
+
ID ID_trace_ev_loop_enter;
|
7
|
+
ID ID_trace_ev_loop_leave;
|
8
|
+
ID ID_trace_run;
|
9
|
+
ID ID_trace_runnable;
|
10
|
+
ID ID_trace_terminate;
|
11
|
+
ID ID_trace_wait;
|
12
|
+
|
13
|
+
VALUE SYM_dead;
|
14
|
+
VALUE SYM_running;
|
15
|
+
VALUE SYM_runnable;
|
16
|
+
VALUE SYM_waiting;
|
17
|
+
|
18
|
+
VALUE SYM_fiber_create;
|
19
|
+
VALUE SYM_fiber_ev_loop_enter;
|
20
|
+
VALUE SYM_fiber_ev_loop_leave;
|
21
|
+
VALUE SYM_fiber_run;
|
22
|
+
VALUE SYM_fiber_schedule;
|
23
|
+
VALUE SYM_fiber_switchpoint;
|
24
|
+
VALUE SYM_fiber_terminate;
|
25
|
+
|
26
|
+
static VALUE Fiber_safe_transfer(int argc, VALUE *argv, VALUE self) {
|
27
|
+
VALUE arg = (argc == 0) ? Qnil : argv[0];
|
28
|
+
VALUE ret = rb_funcall(self, ID_transfer, 1, arg);
|
29
|
+
|
30
|
+
TEST_RESUME_EXCEPTION(ret);
|
31
|
+
RB_GC_GUARD(ret);
|
32
|
+
return ret;
|
33
|
+
}
|
34
|
+
|
35
|
+
inline VALUE Fiber_auto_async(VALUE self) {
|
36
|
+
VALUE async = rb_ivar_get(self, ID_ivar_auto_async);
|
37
|
+
if (async == Qnil) {
|
38
|
+
async = rb_funcall(cGyro_Async, ID_new, 0);
|
39
|
+
rb_ivar_set(self, ID_ivar_auto_async, async);
|
40
|
+
}
|
41
|
+
return async;
|
42
|
+
}
|
43
|
+
|
44
|
+
inline VALUE Fiber_auto_io(VALUE self) {
|
45
|
+
VALUE io = rb_ivar_get(self, ID_ivar_auto_io);
|
46
|
+
if (io == Qnil) {
|
47
|
+
io = rb_funcall(cGyro_IO, ID_new, 2, Qnil, Qnil);
|
48
|
+
rb_ivar_set(self, ID_ivar_auto_io, io);
|
49
|
+
}
|
50
|
+
return io;
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE Fiber_schedule(int argc, VALUE *argv, VALUE self) {
|
54
|
+
VALUE value = (argc == 0) ? Qnil : argv[0];
|
55
|
+
Fiber_make_runnable(self, value);
|
56
|
+
return self;
|
57
|
+
}
|
58
|
+
|
59
|
+
static VALUE Fiber_state(VALUE self) {
|
60
|
+
if (!rb_fiber_alive_p(self) || (rb_ivar_get(self, ID_ivar_running) == Qfalse))
|
61
|
+
return SYM_dead;
|
62
|
+
if (rb_fiber_current() == self) return SYM_running;
|
63
|
+
if (rb_ivar_get(self, ID_runnable) != Qnil) return SYM_runnable;
|
64
|
+
|
65
|
+
return SYM_waiting;
|
66
|
+
}
|
67
|
+
|
68
|
+
void Fiber_make_runnable(VALUE fiber, VALUE value) {
|
69
|
+
VALUE thread = rb_ivar_get(fiber, ID_ivar_thread);
|
70
|
+
if (thread != Qnil) {
|
71
|
+
Thread_schedule_fiber(thread, fiber, value);
|
72
|
+
}
|
73
|
+
else {
|
74
|
+
rb_warn("No thread set for fiber");
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
void Init_Fiber() {
|
79
|
+
VALUE cFiber = rb_const_get(rb_cObject, rb_intern("Fiber"));
|
80
|
+
rb_define_method(cFiber, "auto_async", Fiber_auto_async, 0);
|
81
|
+
rb_define_method(cFiber, "safe_transfer", Fiber_safe_transfer, -1);
|
82
|
+
rb_define_method(cFiber, "schedule", Fiber_schedule, -1);
|
83
|
+
rb_define_method(cFiber, "state", Fiber_state, 0);
|
84
|
+
|
85
|
+
ID_ivar_auto_async = rb_intern("@auto_async");
|
86
|
+
|
87
|
+
SYM_dead = ID2SYM(rb_intern("dead"));
|
88
|
+
SYM_running = ID2SYM(rb_intern("running"));
|
89
|
+
SYM_runnable = ID2SYM(rb_intern("runnable"));
|
90
|
+
SYM_waiting = ID2SYM(rb_intern("waiting"));
|
91
|
+
rb_global_variable(&SYM_dead);
|
92
|
+
rb_global_variable(&SYM_running);
|
93
|
+
rb_global_variable(&SYM_runnable);
|
94
|
+
rb_global_variable(&SYM_waiting);
|
95
|
+
|
96
|
+
ID_fiber_trace = rb_intern("__fiber_trace__");
|
97
|
+
|
98
|
+
SYM_fiber_create = ID2SYM(rb_intern("fiber_create"));
|
99
|
+
SYM_fiber_ev_loop_enter = ID2SYM(rb_intern("fiber_ev_loop_enter"));
|
100
|
+
SYM_fiber_ev_loop_leave = ID2SYM(rb_intern("fiber_ev_loop_leave"));
|
101
|
+
SYM_fiber_run = ID2SYM(rb_intern("fiber_run"));
|
102
|
+
SYM_fiber_schedule = ID2SYM(rb_intern("fiber_schedule"));
|
103
|
+
SYM_fiber_switchpoint = ID2SYM(rb_intern("fiber_switchpoint"));
|
104
|
+
SYM_fiber_terminate = ID2SYM(rb_intern("fiber_terminate"));
|
105
|
+
|
106
|
+
rb_global_variable(&SYM_fiber_create);
|
107
|
+
rb_global_variable(&SYM_fiber_ev_loop_enter);
|
108
|
+
rb_global_variable(&SYM_fiber_ev_loop_leave);
|
109
|
+
rb_global_variable(&SYM_fiber_run);
|
110
|
+
rb_global_variable(&SYM_fiber_schedule);
|
111
|
+
rb_global_variable(&SYM_fiber_switchpoint);
|
112
|
+
rb_global_variable(&SYM_fiber_terminate);
|
113
|
+
}
|