polyphony 0.39 → 0.43.1

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.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +11 -2
  3. data/.gitignore +2 -2
  4. data/.rubocop.yml +30 -0
  5. data/CHANGELOG.md +23 -4
  6. data/Gemfile.lock +15 -12
  7. data/README.md +2 -1
  8. data/Rakefile +3 -3
  9. data/TODO.md +27 -97
  10. data/docs/_config.yml +56 -7
  11. data/docs/_sass/custom/custom.scss +6 -26
  12. data/docs/_sass/overrides.scss +0 -46
  13. data/docs/{user-guide → _user-guide}/all-about-timers.md +0 -0
  14. data/docs/_user-guide/index.md +9 -0
  15. data/docs/{user-guide → _user-guide}/web-server.md +0 -0
  16. data/docs/api-reference/fiber.md +2 -2
  17. data/docs/api-reference/index.md +9 -0
  18. data/docs/api-reference/polyphony-process.md +1 -1
  19. data/docs/api-reference/thread.md +1 -1
  20. data/docs/faq.md +21 -11
  21. data/docs/favicon.ico +0 -0
  22. data/docs/getting-started/index.md +10 -0
  23. data/docs/getting-started/installing.md +2 -6
  24. data/docs/getting-started/overview.md +486 -0
  25. data/docs/getting-started/tutorial.md +27 -19
  26. data/docs/index.md +6 -2
  27. data/docs/main-concepts/concurrency.md +0 -5
  28. data/docs/main-concepts/design-principles.md +69 -21
  29. data/docs/main-concepts/extending.md +1 -1
  30. data/docs/main-concepts/index.md +9 -0
  31. data/docs/polyphony-logo.png +0 -0
  32. data/examples/core/01-spinning-up-fibers.rb +1 -0
  33. data/examples/core/03-interrupting.rb +4 -1
  34. data/examples/core/04-handling-signals.rb +19 -0
  35. data/examples/core/xx-agent.rb +102 -0
  36. data/examples/core/xx-sleeping.rb +14 -6
  37. data/examples/io/tunnel.rb +48 -0
  38. data/examples/io/xx-irb.rb +1 -1
  39. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
  40. data/examples/performance/thread-vs-fiber/polyphony_server.rb +13 -36
  41. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  42. data/examples/performance/xx-array.rb +11 -0
  43. data/examples/performance/xx-fiber-switch.rb +9 -0
  44. data/examples/performance/xx-snooze.rb +15 -0
  45. data/ext/{gyro → polyphony}/extconf.rb +2 -2
  46. data/ext/{gyro → polyphony}/fiber.c +17 -23
  47. data/ext/{gyro → polyphony}/libev.c +0 -0
  48. data/ext/{gyro → polyphony}/libev.h +0 -0
  49. data/ext/polyphony/libev_agent.c +718 -0
  50. data/ext/polyphony/libev_queue.c +216 -0
  51. data/ext/polyphony/polyphony.c +73 -0
  52. data/ext/{gyro/gyro.h → polyphony/polyphony.h} +19 -39
  53. data/ext/polyphony/polyphony_ext.c +21 -0
  54. data/ext/polyphony/thread.c +200 -0
  55. data/ext/{gyro → polyphony}/tracing.c +1 -1
  56. data/lib/polyphony.rb +19 -14
  57. data/lib/polyphony/adapters/irb.rb +1 -1
  58. data/lib/polyphony/adapters/postgres.rb +6 -5
  59. data/lib/polyphony/adapters/process.rb +5 -5
  60. data/lib/polyphony/adapters/trace.rb +28 -28
  61. data/lib/polyphony/core/channel.rb +3 -3
  62. data/lib/polyphony/core/exceptions.rb +1 -1
  63. data/lib/polyphony/core/global_api.rb +13 -11
  64. data/lib/polyphony/core/resource_pool.rb +3 -3
  65. data/lib/polyphony/core/sync.rb +2 -2
  66. data/lib/polyphony/core/thread_pool.rb +6 -6
  67. data/lib/polyphony/core/throttler.rb +13 -6
  68. data/lib/polyphony/event.rb +27 -0
  69. data/lib/polyphony/extensions/core.rb +22 -14
  70. data/lib/polyphony/extensions/fiber.rb +4 -4
  71. data/lib/polyphony/extensions/io.rb +59 -25
  72. data/lib/polyphony/extensions/openssl.rb +36 -16
  73. data/lib/polyphony/extensions/socket.rb +28 -10
  74. data/lib/polyphony/extensions/thread.rb +16 -9
  75. data/lib/polyphony/net.rb +9 -9
  76. data/lib/polyphony/version.rb +1 -1
  77. data/polyphony.gemspec +4 -4
  78. data/test/helper.rb +12 -8
  79. data/test/test_agent.rb +124 -0
  80. data/test/{test_async.rb → test_event.rb} +15 -7
  81. data/test/test_ext.rb +25 -4
  82. data/test/test_fiber.rb +19 -10
  83. data/test/test_global_api.rb +11 -11
  84. data/test/test_io.rb +44 -29
  85. data/test/test_queue.rb +74 -0
  86. data/test/test_signal.rb +3 -40
  87. data/test/test_socket.rb +34 -0
  88. data/test/test_thread.rb +38 -17
  89. data/test/test_thread_pool.rb +2 -2
  90. data/test/test_throttler.rb +5 -3
  91. data/test/test_trace.rb +6 -5
  92. metadata +41 -43
  93. data/docs/_includes/nav.html +0 -51
  94. data/docs/_includes/prevnext.html +0 -17
  95. data/docs/_layouts/default.html +0 -106
  96. data/docs/api-reference.md +0 -11
  97. data/docs/api-reference/gyro-async.md +0 -57
  98. data/docs/api-reference/gyro-child.md +0 -29
  99. data/docs/api-reference/gyro-queue.md +0 -44
  100. data/docs/api-reference/gyro-timer.md +0 -51
  101. data/docs/api-reference/gyro.md +0 -25
  102. data/docs/getting-started.md +0 -10
  103. data/docs/main-concepts.md +0 -10
  104. data/docs/user-guide.md +0 -10
  105. data/examples/core/forever_sleep.rb +0 -19
  106. data/ext/gyro/async.c +0 -162
  107. data/ext/gyro/child.c +0 -141
  108. data/ext/gyro/gyro.c +0 -103
  109. data/ext/gyro/gyro_ext.c +0 -33
  110. data/ext/gyro/io.c +0 -489
  111. data/ext/gyro/queue.c +0 -142
  112. data/ext/gyro/selector.c +0 -228
  113. data/ext/gyro/signal.c +0 -133
  114. data/ext/gyro/socket.c +0 -210
  115. data/ext/gyro/thread.c +0 -308
  116. data/ext/gyro/timer.c +0 -151
  117. data/test/test_timer.rb +0 -32
@@ -1,210 +0,0 @@
1
- #include "gyro.h"
2
- #include <sys/socket.h>
3
-
4
- static VALUE cTCPSocket;
5
-
6
- ///////////////////////////////////////////////////////////////////////////
7
-
8
- struct rsock_send_arg {
9
- int fd, flags;
10
- VALUE mesg;
11
- struct sockaddr *to;
12
- socklen_t tolen;
13
- };
14
-
15
- #define StringValue(v) rb_string_value(&(v))
16
- #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
17
-
18
- VALUE
19
- rsock_sockaddr_string_value(volatile VALUE *v)
20
- {
21
- // VALUE val = *v;
22
- // if (IS_ADDRINFO(val)) {
23
- // *v = addrinfo_to_sockaddr(val);
24
- // }
25
- StringValue(*v);
26
- return *v;
27
- }
28
-
29
- #define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v))
30
- #define RSTRING_LENINT(str) rb_long2int(RSTRING_LEN(str))
31
- #ifndef RSTRING_SOCKLEN
32
- # define RSTRING_SOCKLEN (socklen_t)RSTRING_LENINT
33
- #endif
34
-
35
- #if defined __APPLE__
36
- # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
37
- #else
38
- # define do_write_retry(code) ret = code
39
- #endif
40
-
41
- VALUE
42
- rsock_sendto_blocking(void *data)
43
- {
44
- struct rsock_send_arg *arg = data;
45
- VALUE mesg = arg->mesg;
46
- ssize_t ret;
47
- do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
48
- arg->flags, arg->to, arg->tolen));
49
- return (VALUE)ret;
50
- }
51
-
52
- VALUE
53
- rsock_send_blocking(void *data)
54
- {
55
- struct rsock_send_arg *arg = data;
56
- VALUE mesg = arg->mesg;
57
- ssize_t ret;
58
- do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
59
- arg->flags));
60
- return (VALUE)ret;
61
- }
62
-
63
- ///////////////////////////////////////////////////////////////////////////
64
-
65
- static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
66
- VALUE underlying_socket = rb_iv_get(sock, "@io");
67
- if (!NIL_P(underlying_socket)) sock = underlying_socket;
68
- struct rsock_send_arg arg;
69
- VALUE flags, to;
70
- rb_io_t *fptr;
71
- ssize_t n;
72
- rb_blocking_function_t *func;
73
- const char *funcname;
74
- VALUE write_watcher = Qnil;
75
-
76
- rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
77
-
78
- StringValue(arg.mesg);
79
-
80
- if (!NIL_P(to)) {
81
- SockAddrStringValue(to);
82
- to = rb_str_new4(to);
83
- arg.to = (struct sockaddr *)RSTRING_PTR(to);
84
- arg.tolen = RSTRING_SOCKLEN(to);
85
- func = rsock_sendto_blocking;
86
- funcname = "sendto(2)";
87
- }
88
- else {
89
- func = rsock_send_blocking;
90
- funcname = "send(2)";
91
- }
92
- GetOpenFile(sock, fptr);
93
- rb_io_set_nonblock(fptr);
94
- arg.fd = fptr->fd;
95
- arg.flags = NUM2INT(flags);
96
- while ((n = (ssize_t)func(&arg)) < 0) {
97
- if (NIL_P(write_watcher))
98
- write_watcher = Gyro_IO_auto_io(fptr->fd, EV_WRITE);
99
- Gyro_IO_await(write_watcher);
100
- }
101
- return SSIZET2NUM(n);
102
- }
103
-
104
- static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
105
- VALUE underlying_socket = rb_iv_get(sock, "@io");
106
- if (!NIL_P(underlying_socket)) sock = underlying_socket;
107
- long len = argc >= 1 ? NUM2LONG(argv[0]) : 8192;
108
- if (len < 0) {
109
- rb_raise(rb_eArgError, "negative length %ld given", len);
110
- }
111
-
112
- rb_io_t *fptr;
113
- long n;
114
- int shrinkable;
115
- VALUE read_watcher = Qnil;
116
-
117
-
118
- VALUE str = argc >= 3 ? argv[2] : Qnil;
119
-
120
- shrinkable = io_setstrbuf(&str, len);
121
- OBJ_TAINT(str);
122
- GetOpenFile(sock, fptr);
123
- // rb_io_set_nonblock(fptr);
124
- rb_io_check_byte_readable(fptr);
125
-
126
- if (len == 0)
127
- return str;
128
-
129
- while (1) {
130
- n = recv(fptr->fd, RSTRING_PTR(str), len, MSG_DONTWAIT);
131
- if (n < 0) {
132
- int e = errno;
133
- if (e == EWOULDBLOCK || e == EAGAIN) {
134
- if (NIL_P(read_watcher))
135
- read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
136
- Gyro_IO_await(read_watcher);
137
- }
138
- else
139
- rb_syserr_fail(e, strerror(e));
140
- // rb_syserr_fail_path(e, fptr->pathv);
141
- }
142
- else
143
- break;
144
- }
145
-
146
- io_set_read_length(str, n, shrinkable);
147
- io_enc_str(str, fptr);
148
-
149
- if (n == 0)
150
- return Qnil;
151
-
152
- return str;
153
- }
154
-
155
- static VALUE Socket_accept(VALUE sock) {
156
- rb_io_t *fptr;
157
- int fd;
158
- struct sockaddr addr;
159
- socklen_t len = (socklen_t)sizeof addr;
160
- VALUE read_watcher = Qnil;
161
-
162
- GetOpenFile(sock, fptr);
163
- rb_io_set_nonblock(fptr);
164
-
165
- while (1) {
166
- fd = accept(fptr->fd, &addr, &len);
167
-
168
- if (fd < 0) {
169
- int e = errno;
170
- if (e == EWOULDBLOCK || e == EAGAIN) {
171
- if (NIL_P(read_watcher))
172
- read_watcher = Gyro_IO_auto_io(fptr->fd, EV_READ);
173
- Gyro_IO_await(read_watcher);
174
- }
175
- else
176
- rb_syserr_fail(e, strerror(e));
177
- // rb_syserr_fail_path(e, fptr->pathv);
178
- }
179
- else {
180
- VALUE connection = rb_obj_alloc(cTCPSocket);
181
- rb_io_t *fp;
182
- MakeOpenFile(connection, fp);
183
- rb_update_max_fd(fd);
184
- fp->fd = fd;
185
- fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
186
- rb_io_ascii8bit_binmode(connection);
187
- rb_io_set_nonblock(fp);
188
- rb_io_synchronized(fp);
189
- // if (rsock_do_not_reverse_lookup) {
190
- // fp->mode |= FMODE_NOREVLOOKUP;
191
- // }
192
-
193
- return connection;
194
- }
195
- }
196
- }
197
-
198
- void Init_Socket() {
199
- rb_require("socket");
200
- VALUE cBasicSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
201
-
202
- rb_define_method(cBasicSocket, "send", BasicSocket_send, -1);
203
- rb_define_method(cBasicSocket, "recv", BasicSocket_recv, -1);
204
-
205
- VALUE cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
206
-
207
- rb_define_method(cSocket, "accept", Socket_accept, 0);
208
-
209
- cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
210
- }
@@ -1,308 +0,0 @@
1
- #include "gyro.h"
2
-
3
- static VALUE cQueue;
4
-
5
- static ID ID_create_event_selector;
6
- static ID ID_deactivate_all_watchers_post_fork;
7
- static ID ID_empty;
8
- static ID ID_fiber_ref_count;
9
- static ID ID_ivar_event_selector_proc;
10
- static ID ID_ivar_event_selector;
11
- static ID ID_ivar_join_wait_queue;
12
- static ID ID_ivar_main_fiber;
13
- static ID ID_ivar_result;
14
- static ID ID_ivar_terminated;
15
- static ID ID_pop;
16
- static ID ID_push;
17
- static ID ID_run_queue;
18
- static ID ID_runnable_next;
19
- static ID ID_stop;
20
-
21
- VALUE event_selector_factory_proc(RB_BLOCK_CALL_FUNC_ARGLIST(args, klass)) {
22
- return rb_funcall(klass, ID_new, 1, rb_ary_entry(args, 0));
23
- }
24
-
25
- static VALUE Thread_event_selector_set_proc(VALUE self, VALUE proc) {
26
- if (!rb_obj_is_proc(proc)) {
27
- proc = rb_proc_new(event_selector_factory_proc, proc);
28
- }
29
- rb_ivar_set(self, ID_ivar_event_selector_proc, proc);
30
- return self;
31
- }
32
-
33
- static VALUE Thread_create_event_selector(VALUE self, VALUE thread) {
34
- VALUE selector_proc = rb_ivar_get(self, ID_ivar_event_selector_proc);
35
- if (selector_proc == Qnil) {
36
- rb_raise(rb_eRuntimeError, "No event_selector_proc defined");
37
- }
38
-
39
- return rb_funcall(selector_proc, ID_call, 1, thread);
40
- }
41
-
42
- static VALUE Thread_setup_fiber_scheduling(VALUE self) {
43
- rb_ivar_set(self, ID_ivar_main_fiber, rb_fiber_current());
44
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(0));
45
- VALUE queue = rb_ary_new();
46
- rb_ivar_set(self, ID_run_queue, queue);
47
- VALUE selector = rb_funcall(rb_cThread, ID_create_event_selector, 1, self);
48
- rb_ivar_set(self, ID_ivar_event_selector, selector);
49
-
50
- return self;
51
- }
52
-
53
- static VALUE Thread_stop_event_selector(VALUE self) {
54
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
55
- if (selector != Qnil) {
56
- rb_funcall(selector, ID_stop, 0);
57
- }
58
- // Nullify the selector in order to prevent running the
59
- // selector after the thread is done running.
60
- rb_ivar_set(self, ID_ivar_event_selector, Qnil);
61
-
62
- return self;
63
- }
64
-
65
- static VALUE Thread_deactivate_all_watchers_post_fork(VALUE self) {
66
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
67
- if (selector != Qnil) {
68
- rb_funcall(selector, ID_deactivate_all_watchers_post_fork, 0);
69
- }
70
-
71
- return self;
72
- }
73
-
74
- VALUE Thread_ref(VALUE self) {
75
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
76
- int new_count = NUM2INT(count) + 1;
77
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(new_count));
78
- return self;
79
- }
80
-
81
- VALUE Thread_unref(VALUE self) {
82
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
83
- int new_count = NUM2INT(count) - 1;
84
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(new_count));
85
- return self;
86
- }
87
-
88
- int Thread_fiber_ref_count(VALUE self) {
89
- VALUE count = rb_ivar_get(self, ID_fiber_ref_count);
90
- return NUM2INT(count);
91
- }
92
-
93
- void Thread_fiber_reset_ref_count(VALUE self) {
94
- rb_ivar_set(self, ID_fiber_ref_count, INT2NUM(0));
95
- }
96
-
97
- static VALUE SYM_scheduled_fibers;
98
- static VALUE SYM_pending_watchers;
99
-
100
- static VALUE Thread_fiber_scheduling_stats(VALUE self) {
101
- VALUE stats = rb_hash_new();
102
- VALUE queue = rb_ivar_get(self, ID_run_queue);
103
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
104
-
105
- long scheduled_count = RARRAY_LEN(queue);
106
- rb_hash_aset(stats, SYM_scheduled_fibers, INT2NUM(scheduled_count));
107
-
108
- long pending_count = Gyro_Selector_pending_count(selector);
109
- rb_hash_aset(stats, SYM_pending_watchers, INT2NUM(pending_count));
110
-
111
- return stats;
112
- }
113
-
114
- VALUE Thread_schedule_fiber(VALUE self, VALUE fiber, VALUE value) {
115
- if (rb_fiber_alive_p(fiber) != Qtrue) {
116
- return self;
117
- }
118
-
119
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
120
- // if fiber is already scheduled, just set the scheduled value, then return
121
- rb_ivar_set(fiber, ID_runnable_value, value);
122
- if (rb_ivar_get(fiber, ID_runnable) != Qnil) {
123
- return self;
124
- }
125
-
126
- VALUE queue = rb_ivar_get(self, ID_run_queue);
127
- rb_ary_push(queue, fiber);
128
- rb_ivar_set(fiber, ID_runnable, Qtrue);
129
-
130
- if (rb_thread_current() != self) {
131
- // if the fiber scheduling is done across threads, we need to make sure the
132
- // target thread is woken up in case it is in the middle of running its
133
- // event selector. Otherwise it's gonna be stuck waiting for an event to
134
- // happen, not knowing that it there's already a fiber ready to run in its
135
- // run queue.
136
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
137
- if (selector != Qnil) {
138
- Gyro_Selector_break_out_of_ev_loop(selector);
139
- }
140
- }
141
- return self;
142
- }
143
-
144
- VALUE Thread_schedule_fiber_with_priority(VALUE self, VALUE fiber, VALUE value) {
145
- if (rb_fiber_alive_p(fiber) != Qtrue) {
146
- return self;
147
- }
148
- FIBER_TRACE(3, SYM_fiber_schedule, fiber, value);
149
- rb_ivar_set(fiber, ID_runnable_value, value);
150
-
151
- VALUE queue = rb_ivar_get(self, ID_run_queue);
152
-
153
- // if fiber is already scheduled, remove it from the run queue
154
- if (rb_ivar_get(fiber, ID_runnable) != Qnil) {
155
- rb_ary_delete(queue, fiber);
156
- } else {
157
- rb_ivar_set(fiber, ID_runnable, Qtrue);
158
- }
159
-
160
- // the fiber is given priority by putting it at the front of the run queue
161
- rb_ary_unshift(queue, fiber);
162
-
163
- if (rb_thread_current() != self) {
164
- // if the fiber scheduling is done across threads, we need to make sure the
165
- // target thread is woken up in case it is in the middle of running its
166
- // event selector. Otherwise it's gonna be stuck waiting for an event to
167
- // happen, not knowing that it there's already a fiber ready to run in its
168
- // run queue.
169
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
170
- if (selector != Qnil) {
171
- Gyro_Selector_break_out_of_ev_loop(selector);
172
- }
173
- }
174
- return self;
175
- }
176
-
177
- VALUE Thread_switch_fiber(VALUE self) {
178
- VALUE current_fiber = rb_fiber_current();
179
- if (__tracing_enabled__) {
180
- if (rb_ivar_get(current_fiber, ID_ivar_running) != Qfalse) {
181
- rb_funcall(rb_cObject, ID_fiber_trace, 2, SYM_fiber_switchpoint, current_fiber);
182
- }
183
- }
184
- VALUE queue = rb_ivar_get(self, ID_run_queue);
185
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
186
-
187
- VALUE next_fiber;
188
-
189
- while (1) {
190
- next_fiber = rb_ary_shift(queue);
191
- // if (break_flag != 0) {
192
- // return Qnil;
193
- // }
194
- int ref_count = Thread_fiber_ref_count(self);
195
- if (next_fiber != Qnil) {
196
- if (ref_count > 0) {
197
- // this mechanism prevents event starvation in case the run queue never
198
- // empties
199
- Gyro_Selector_run_no_wait(selector, current_fiber, RARRAY_LEN(queue));
200
- }
201
- break;
202
- }
203
- if (ref_count == 0) {
204
- break;
205
- }
206
-
207
- Gyro_Selector_run(selector, current_fiber);
208
- }
209
-
210
- if (next_fiber == Qnil) {
211
- return Qnil;
212
- }
213
-
214
- // run next fiber
215
- VALUE value = rb_ivar_get(next_fiber, ID_runnable_value);
216
- FIBER_TRACE(3, SYM_fiber_run, next_fiber, value);
217
-
218
- rb_ivar_set(next_fiber, ID_runnable, Qnil);
219
- RB_GC_GUARD(next_fiber);
220
- RB_GC_GUARD(value);
221
- return rb_funcall(next_fiber, ID_transfer, 1, value);
222
- }
223
-
224
- VALUE Thread_reset_fiber_scheduling(VALUE self) {
225
- VALUE queue = rb_ivar_get(self, ID_run_queue);
226
- rb_ary_clear(queue);
227
- Thread_fiber_reset_ref_count(self);
228
- return self;
229
- }
230
-
231
- VALUE Thread_post_fork(VALUE self) {
232
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
233
- Gyro_Selector_post_fork(selector);
234
-
235
- return self;
236
- }
237
-
238
- VALUE Gyro_switchpoint() {
239
- VALUE thread = rb_thread_current();
240
- Thread_ref(thread);
241
- VALUE ret = Thread_switch_fiber(thread);
242
- Thread_unref(thread);
243
- RB_GC_GUARD(ret);
244
- return ret;
245
- }
246
-
247
- VALUE Thread_current_event_selector() {
248
- return rb_ivar_get(rb_thread_current(), ID_ivar_event_selector);
249
- }
250
-
251
- VALUE Thread_fiber_break_out_of_ev_loop(VALUE self, VALUE fiber, VALUE resume_obj) {
252
- VALUE selector = rb_ivar_get(self, ID_ivar_event_selector);
253
- if (fiber != Qnil) {
254
- Thread_schedule_fiber_with_priority(self, fiber, resume_obj);
255
- }
256
-
257
- if (Gyro_Selector_break_out_of_ev_loop(selector) == Qnil) {
258
- // we're not inside the ev_loop, so we just do a switchpoint
259
- Thread_switch_fiber(self);
260
- }
261
-
262
- return self;
263
- }
264
-
265
- void Init_Thread() {
266
- cQueue = rb_const_get(rb_cObject, rb_intern("Queue"));
267
-
268
- rb_define_singleton_method(rb_cThread, "event_selector=", Thread_event_selector_set_proc, 1);
269
- rb_define_singleton_method(rb_cThread, "create_event_selector", Thread_create_event_selector, 1);
270
-
271
- rb_define_method(rb_cThread, "fiber_ref", Thread_ref, 0);
272
- rb_define_method(rb_cThread, "fiber_unref", Thread_unref, 0);
273
-
274
- rb_define_method(rb_cThread, "post_fork", Thread_post_fork, 0);
275
-
276
- rb_define_method(rb_cThread, "setup_fiber_scheduling", Thread_setup_fiber_scheduling, 0);
277
- rb_define_method(rb_cThread, "stop_event_selector", Thread_stop_event_selector, 0);
278
- rb_define_method(rb_cThread, "deactivate_all_watchers_post_fork", Thread_deactivate_all_watchers_post_fork, 0);
279
- rb_define_method(rb_cThread, "reset_fiber_scheduling", Thread_reset_fiber_scheduling, 0);
280
- rb_define_method(rb_cThread, "fiber_scheduling_stats", Thread_fiber_scheduling_stats, 0);
281
- rb_define_method(rb_cThread, "break_out_of_ev_loop", Thread_fiber_break_out_of_ev_loop, 2);
282
-
283
- rb_define_method(rb_cThread, "schedule_fiber", Thread_schedule_fiber, 2);
284
- rb_define_method(rb_cThread, "schedule_fiber_with_priority",
285
- Thread_schedule_fiber_with_priority, 2);
286
- rb_define_method(rb_cThread, "switch_fiber", Thread_switch_fiber, 0);
287
-
288
- ID_create_event_selector = rb_intern("create_event_selector");
289
- ID_deactivate_all_watchers_post_fork = rb_intern("deactivate_all_watchers_post_fork");
290
- ID_empty = rb_intern("empty?");
291
- ID_fiber_ref_count = rb_intern("fiber_ref_count");
292
- ID_ivar_event_selector = rb_intern("@event_selector");
293
- ID_ivar_event_selector_proc = rb_intern("@event_selector_proc");
294
- ID_ivar_join_wait_queue = rb_intern("@join_wait_queue");
295
- ID_ivar_main_fiber = rb_intern("@main_fiber");
296
- ID_ivar_result = rb_intern("@result");
297
- ID_ivar_terminated = rb_intern("@terminated");
298
- ID_pop = rb_intern("pop");
299
- ID_push = rb_intern("push");
300
- ID_run_queue = rb_intern("run_queue");
301
- ID_runnable_next = rb_intern("runnable_next");
302
- ID_stop = rb_intern("stop");
303
-
304
- SYM_scheduled_fibers = ID2SYM(rb_intern("scheduled_fibers"));
305
- SYM_pending_watchers = ID2SYM(rb_intern("pending_watchers"));
306
- rb_global_variable(&SYM_scheduled_fibers);
307
- rb_global_variable(&SYM_pending_watchers);
308
- }