polyphony 0.99 → 0.99.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +1 -1
- data/.rubocop.yml +3 -3
- data/.yardopts +30 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE +1 -1
- data/README.md +63 -29
- data/Rakefile +1 -5
- data/TODO.md +0 -4
- data/docs/{main-concepts/concurrency.md → concurrency.md} +2 -9
- data/docs/{main-concepts/design-principles.md → design-principles.md} +3 -9
- data/docs/{main-concepts/exception-handling.md → exception-handling.md} +2 -9
- data/docs/{main-concepts/extending.md → extending.md} +2 -9
- data/docs/faq.md +3 -16
- data/docs/{main-concepts/fiber-scheduling.md → fiber-scheduling.md} +1 -9
- data/docs/link_rewriter.rb +16 -0
- data/docs/{getting-started/overview.md → overview.md} +1 -30
- data/docs/{getting-started/tutorial.md → tutorial.md} +3 -28
- data/docs/{_posts/2020-07-26-polyphony-0.44.md → whats-new.md} +3 -1
- data/examples/adapters/redis_client.rb +3 -2
- data/examples/io/echo_server.rb +1 -1
- data/examples/io/echo_server_plain_ruby.rb +26 -0
- data/ext/polyphony/backend_io_uring.c +154 -9
- data/ext/polyphony/backend_io_uring_context.c +21 -12
- data/ext/polyphony/backend_io_uring_context.h +12 -7
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/extconf.rb +24 -8
- data/ext/polyphony/fiber.c +79 -2
- data/ext/polyphony/io_extensions.c +53 -0
- data/ext/polyphony/pipe.c +42 -2
- data/ext/polyphony/polyphony.c +345 -31
- data/ext/polyphony/polyphony.h +9 -2
- data/ext/polyphony/queue.c +181 -0
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/runqueue.c +8 -1
- data/ext/polyphony/runqueue_ring_buffer.c +13 -0
- data/ext/polyphony/runqueue_ring_buffer.h +2 -1
- data/ext/polyphony/socket_extensions.c +6 -0
- data/ext/polyphony/thread.c +34 -2
- data/lib/polyphony/adapters/process.rb +11 -1
- data/lib/polyphony/adapters/sequel.rb +1 -1
- data/lib/polyphony/core/channel.rb +2 -0
- data/lib/polyphony/core/debug.rb +1 -1
- data/lib/polyphony/core/global_api.rb +25 -24
- data/lib/polyphony/core/resource_pool.rb +7 -6
- data/lib/polyphony/core/sync.rb +2 -2
- data/lib/polyphony/core/thread_pool.rb +3 -3
- data/lib/polyphony/core/timer.rb +8 -8
- data/lib/polyphony/extensions/exception.rb +2 -0
- data/lib/polyphony/extensions/fiber.rb +15 -13
- data/lib/polyphony/extensions/io.rb +127 -5
- data/lib/polyphony/extensions/kernel.rb +20 -2
- data/lib/polyphony/extensions/openssl.rb +100 -11
- data/lib/polyphony/extensions/pipe.rb +103 -7
- data/lib/polyphony/extensions/process.rb +13 -1
- data/lib/polyphony/extensions/socket.rb +93 -27
- data/lib/polyphony/extensions/thread.rb +9 -1
- data/lib/polyphony/extensions/timeout.rb +1 -1
- data/lib/polyphony/version.rb +2 -1
- data/lib/polyphony.rb +27 -7
- data/polyphony.gemspec +1 -8
- data/test/stress.rb +1 -1
- data/test/test_global_api.rb +45 -7
- data/test/test_socket.rb +96 -0
- data/test/test_timer.rb +5 -5
- metadata +17 -40
- data/docs/_config.yml +0 -64
- data/docs/_includes/head.html +0 -40
- data/docs/_includes/title.html +0 -1
- data/docs/_sass/custom/custom.scss +0 -10
- data/docs/_sass/overrides.scss +0 -0
- data/docs/api-reference/exception.md +0 -31
- data/docs/api-reference/fiber.md +0 -425
- data/docs/api-reference/index.md +0 -9
- data/docs/api-reference/io.md +0 -36
- data/docs/api-reference/object.md +0 -99
- data/docs/api-reference/polyphony-baseexception.md +0 -33
- data/docs/api-reference/polyphony-cancel.md +0 -26
- data/docs/api-reference/polyphony-moveon.md +0 -24
- data/docs/api-reference/polyphony-net.md +0 -20
- data/docs/api-reference/polyphony-process.md +0 -28
- data/docs/api-reference/polyphony-resourcepool.md +0 -59
- data/docs/api-reference/polyphony-restart.md +0 -18
- data/docs/api-reference/polyphony-terminate.md +0 -18
- data/docs/api-reference/polyphony-threadpool.md +0 -67
- data/docs/api-reference/polyphony-throttler.md +0 -77
- data/docs/api-reference/polyphony.md +0 -36
- data/docs/api-reference/thread.md +0 -88
- data/docs/favicon.ico +0 -0
- data/docs/getting-started/index.md +0 -10
- data/docs/getting-started/installing.md +0 -34
- /data/{docs/assets/img → assets}/echo-fibers.svg +0 -0
- /data/{docs → assets}/polyphony-logo.png +0 -0
- /data/{docs/assets/img → assets}/sleeping-fiber.svg +0 -0
data/ext/polyphony/pipe.c
CHANGED
@@ -36,7 +36,15 @@ static VALUE Pipe_allocate(VALUE klass) {
|
|
36
36
|
#define GetPipe(obj, pipe) \
|
37
37
|
TypedData_Get_Struct((obj), Pipe_t, &Pipe_type, (pipe))
|
38
38
|
|
39
|
-
|
39
|
+
/* call-seq:
|
40
|
+
* Pipe.new -> pipe
|
41
|
+
*
|
42
|
+
* Creates a new pipe.
|
43
|
+
*
|
44
|
+
* @return [void]
|
45
|
+
*/
|
46
|
+
|
47
|
+
static VALUE Pipe_initialize(VALUE self) {
|
40
48
|
Pipe_t *pipe_struct;
|
41
49
|
GetPipe(self, pipe_struct);
|
42
50
|
|
@@ -72,12 +80,28 @@ int Pipe_get_fd(VALUE self, int write_mode) {
|
|
72
80
|
return pipe->fds[write_mode ? 1 : 0];
|
73
81
|
}
|
74
82
|
|
83
|
+
/* call-seq:
|
84
|
+
* pipe.closed? -> bool
|
85
|
+
*
|
86
|
+
* Returns true if the pipe is closed.
|
87
|
+
*
|
88
|
+
* @return [boolean]
|
89
|
+
*/
|
90
|
+
|
75
91
|
VALUE Pipe_closed_p(VALUE self) {
|
76
92
|
Pipe_t *pipe;
|
77
93
|
GetPipe(self, pipe);
|
78
94
|
return pipe->w_closed ? Qtrue : Qfalse;
|
79
95
|
}
|
80
96
|
|
97
|
+
/* call-seq:
|
98
|
+
* pipe.close -> pipe
|
99
|
+
*
|
100
|
+
* Closes the pipe.
|
101
|
+
*
|
102
|
+
* @return [Pipe] self
|
103
|
+
*/
|
104
|
+
|
81
105
|
VALUE Pipe_close(VALUE self) {
|
82
106
|
Pipe_t *pipe;
|
83
107
|
GetPipe(self, pipe);
|
@@ -89,6 +113,15 @@ VALUE Pipe_close(VALUE self) {
|
|
89
113
|
return self;
|
90
114
|
}
|
91
115
|
|
116
|
+
/* call-seq:
|
117
|
+
* Pipe.fds -> [r, w]
|
118
|
+
*
|
119
|
+
* Returns an array containing the read and write fds for the pipe,
|
120
|
+
* respectively.
|
121
|
+
*
|
122
|
+
* @return [Array<Integer>]
|
123
|
+
*/
|
124
|
+
|
92
125
|
VALUE Pipe_fds(VALUE self) {
|
93
126
|
Pipe_t *pipe;
|
94
127
|
GetPipe(self, pipe);
|
@@ -98,11 +131,18 @@ VALUE Pipe_fds(VALUE self) {
|
|
98
131
|
|
99
132
|
void Init_Pipe(void) {
|
100
133
|
cPipe = rb_define_class_under(mPolyphony, "Pipe", rb_cObject);
|
134
|
+
|
135
|
+
/*
|
136
|
+
* Document-class: Polyphony::Pipe::ClosedPipeError
|
137
|
+
*
|
138
|
+
* An exception raised when trying to read or write to a closed pipe.
|
139
|
+
*/
|
140
|
+
|
101
141
|
cClosedPipeError = rb_define_class_under(cPipe, "ClosedPipeError", rb_eRuntimeError);
|
102
142
|
|
103
143
|
rb_define_alloc_func(cPipe, Pipe_allocate);
|
104
144
|
|
105
|
-
rb_define_method(cPipe, "initialize", Pipe_initialize,
|
145
|
+
rb_define_method(cPipe, "initialize", Pipe_initialize, 0);
|
106
146
|
rb_define_method(cPipe, "closed?", Pipe_closed_p, 0);
|
107
147
|
rb_define_method(cPipe, "close", Pipe_close, 0);
|
108
148
|
rb_define_method(cPipe, "fds", Pipe_fds, 0);
|
data/ext/polyphony/polyphony.c
CHANGED
@@ -11,6 +11,7 @@ ID ID_inspect;
|
|
11
11
|
ID ID_invoke;
|
12
12
|
ID ID_ivar_blocking_mode;
|
13
13
|
ID ID_ivar_io;
|
14
|
+
ID ID_ivar_multishot_accept_queue;
|
14
15
|
ID ID_ivar_parked;
|
15
16
|
ID ID_ivar_runnable;
|
16
17
|
ID ID_ivar_running;
|
@@ -26,10 +27,33 @@ ID ID_R;
|
|
26
27
|
ID ID_W;
|
27
28
|
ID ID_RW;
|
28
29
|
|
30
|
+
/* call-seq:
|
31
|
+
* snooze
|
32
|
+
* Polyphony.snooze
|
33
|
+
*
|
34
|
+
* Switches to the next fiber in the current thread's runqueue after adding the
|
35
|
+
* current fiber to the runqueue. This lets other fibers run, letting the
|
36
|
+
* current fiber eventually continue its work. This call is useful when
|
37
|
+
* performing long-running calculations in order to keep the program responsive.
|
38
|
+
*
|
39
|
+
* @return [void]
|
40
|
+
*/
|
41
|
+
|
29
42
|
VALUE Polyphony_snooze(VALUE self) {
|
30
43
|
return Backend_snooze(BACKEND());
|
31
44
|
}
|
32
45
|
|
46
|
+
/* call-seq:
|
47
|
+
* suspend
|
48
|
+
* Polyphony.suspend
|
49
|
+
*
|
50
|
+
* Switches to the next fiber in the current thread's runqueue without
|
51
|
+
* rescheduling the current fiber. This is useful if the current fiber does not
|
52
|
+
* need to continue or will be scheduled by other means eventually.
|
53
|
+
*
|
54
|
+
* @return [void]
|
55
|
+
*/
|
56
|
+
|
33
57
|
static VALUE Polyphony_suspend(VALUE self) {
|
34
58
|
VALUE ret = Thread_switch_fiber(rb_thread_current());
|
35
59
|
|
@@ -38,102 +62,373 @@ static VALUE Polyphony_suspend(VALUE self) {
|
|
38
62
|
return ret;
|
39
63
|
}
|
40
64
|
|
65
|
+
/* call-seq:
|
66
|
+
* Polyphony.backend_accept(server_socket, socket_class) -> socket
|
67
|
+
*
|
68
|
+
* Accepts an incoming connection on the given server socket, returning an
|
69
|
+
* instance of the given socket class.
|
70
|
+
*
|
71
|
+
* @param server_socket [Socket] socket to accept on
|
72
|
+
* @param socket_class [Class] class of the socket to instantiate for the accepted connection
|
73
|
+
*
|
74
|
+
* @return [Socket] accepted connection
|
75
|
+
*/
|
76
|
+
|
41
77
|
VALUE Polyphony_backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
42
78
|
return Backend_accept(BACKEND(), server_socket, socket_class);
|
43
79
|
}
|
44
80
|
|
81
|
+
/* call-seq:
|
82
|
+
* Polyphony.backend_accept_loop(server_socket, socket_class) { |socket| ... }
|
83
|
+
*
|
84
|
+
* Runs an infinite loop accepting connections on the given server socket,
|
85
|
+
* returning an instance of the given socket class.
|
86
|
+
*
|
87
|
+
* @param server_socket [Socket] socket to accept on
|
88
|
+
* @param socket_class [Class] class of the socket to instantiate for the accepted connection
|
89
|
+
* @yield [Socket] accepted connection passed to the given block
|
90
|
+
* @return [void]
|
91
|
+
*/
|
92
|
+
|
45
93
|
VALUE Polyphony_backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
46
94
|
return Backend_accept_loop(BACKEND(), server_socket, socket_class);
|
47
95
|
}
|
48
96
|
|
97
|
+
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
98
|
+
/* call-seq:
|
99
|
+
* Polyphony.backend_multishot_accept(server_socket) { ... }
|
100
|
+
*
|
101
|
+
* Starts a multishot accept operation on the given server socket. This API is
|
102
|
+
* available only for the io_uring backend.
|
103
|
+
*
|
104
|
+
* @param server_socket [Socket] socket to accept on
|
105
|
+
* @return [void]
|
106
|
+
*/
|
107
|
+
|
108
|
+
VALUE Polyphony_backend_multishot_accept(VALUE self, VALUE server_socket) {
|
109
|
+
return Backend_multishot_accept(BACKEND(), server_socket);
|
110
|
+
}
|
111
|
+
#endif
|
112
|
+
|
113
|
+
|
114
|
+
/* call-seq:
|
115
|
+
* Polyphony.backend_connect(socket, addr, port) -> socket
|
116
|
+
*
|
117
|
+
* Connects the given socket to the given address and port.
|
118
|
+
*
|
119
|
+
* @param io [Socket] socket to connect
|
120
|
+
* @param addr [String] address to connect to
|
121
|
+
* @param port [Integer] port to connect to
|
122
|
+
*
|
123
|
+
* @return [Socket] accepted connection
|
124
|
+
*/
|
125
|
+
|
49
126
|
VALUE Polyphony_backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port) {
|
50
127
|
return Backend_connect(BACKEND(), io, addr, port);
|
51
128
|
}
|
52
129
|
|
130
|
+
/* call-seq:
|
131
|
+
* Polyphony.backend_feed_loop(io, receiver, method)
|
132
|
+
*
|
133
|
+
* Runs a feed loop, reading data from the given io, feeding it to the receiver
|
134
|
+
* with the given method, and passing the receiver's output to the given block.
|
135
|
+
* The loop terminates when EOF is encountered.
|
136
|
+
*
|
137
|
+
* @param io [IO] io to read from
|
138
|
+
* @param receiver [any] an object receiving the data
|
139
|
+
* @param method [Symbol] method used to feed the data to the receiver
|
140
|
+
* @yield [any] data passed to the given block
|
141
|
+
*
|
142
|
+
* @return [void]
|
143
|
+
*/
|
144
|
+
|
53
145
|
VALUE Polyphony_backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
54
146
|
return Backend_feed_loop(BACKEND(), io, receiver, method);
|
55
147
|
}
|
56
148
|
|
149
|
+
/* call-seq:
|
150
|
+
* Polyphony.backend_read(io, buffer, length, to_eof, pos) -> buffer
|
151
|
+
*
|
152
|
+
* Reads from the given io.
|
153
|
+
*
|
154
|
+
* @param io [IO] io to read from
|
155
|
+
* @param buffer [String, nil] buffer to read into
|
156
|
+
* @param length [Integer] maximum bytes to read
|
157
|
+
* @param to_eof [boolean] whether to read to EOF
|
158
|
+
* @param pos [Integer] Position in the buffer to read into
|
159
|
+
*
|
160
|
+
* @return [String] buffer
|
161
|
+
*/
|
162
|
+
|
57
163
|
VALUE Polyphony_backend_read(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE to_eof, VALUE pos) {
|
58
164
|
return Backend_read(BACKEND(), io, buffer, length, to_eof, pos);
|
59
165
|
}
|
60
166
|
|
167
|
+
/* call-seq:
|
168
|
+
* Polyphony.backend_read_loop(io, max_len)
|
169
|
+
*
|
170
|
+
* Performs an infinite loop reading data from the given io. The loop terminates
|
171
|
+
* when EOF is encountered.
|
172
|
+
*
|
173
|
+
* @param io [IO] io to read from
|
174
|
+
* @param maxlen [Integer] maximum bytes to read
|
175
|
+
*
|
176
|
+
* @return [void]
|
177
|
+
*/
|
178
|
+
|
61
179
|
VALUE Polyphony_backend_read_loop(VALUE self, VALUE io, VALUE maxlen) {
|
62
180
|
return Backend_read_loop(BACKEND(), io, maxlen);
|
63
181
|
}
|
64
182
|
|
183
|
+
/* call-seq:
|
184
|
+
* Polyphony.backend_recv(io, buffer, length, pos) -> buffer
|
185
|
+
*
|
186
|
+
* Receives data on the given io.
|
187
|
+
*
|
188
|
+
* @param io [Socket] io to receive on
|
189
|
+
* @param buffer [String, nil] buffer to read into
|
190
|
+
* @param length [Integer] maximum bytes to read
|
191
|
+
* @param pos [Integer] Position in the buffer to read into
|
192
|
+
*
|
193
|
+
* @return [String] buffer
|
194
|
+
*/
|
195
|
+
|
65
196
|
VALUE Polyphony_backend_recv(VALUE self, VALUE io, VALUE buffer, VALUE length, VALUE pos) {
|
66
197
|
return Backend_recv(BACKEND(), io, buffer, length, pos);
|
67
198
|
}
|
68
199
|
|
69
|
-
|
70
|
-
|
200
|
+
/* call-seq:
|
201
|
+
* Polyphony.backend_recvmsg(socket, buffer, maxlen, pos, flags, maxcontrollen, opts) -> buffer
|
202
|
+
*
|
203
|
+
* Receives a message on the given socket.
|
204
|
+
*
|
205
|
+
* @param socket [UDPSocket] io to receive on
|
206
|
+
* @param buffer [String, nil] buffer to read into
|
207
|
+
* @param maxlen [Integer] maximum bytes to read
|
208
|
+
* @param pos [Integer] Position in the buffer to read into
|
209
|
+
* @param flags [Integer] Flags
|
210
|
+
* @param maxcontrollen [Integer] Maximum control bytes
|
211
|
+
* @param opts [Hash] Options
|
212
|
+
*
|
213
|
+
* @return [String] buffer
|
214
|
+
*/
|
215
|
+
|
216
|
+
VALUE Polyphony_backend_recvmsg(VALUE self, VALUE socket, VALUE buffer, VALUE maxlen, VALUE pos, VALUE flags, VALUE maxcontrollen, VALUE opts) {
|
217
|
+
return Backend_recvmsg(BACKEND(), socket, buffer, maxlen, pos, flags, maxcontrollen, opts);
|
71
218
|
}
|
72
219
|
|
73
|
-
|
74
|
-
|
220
|
+
/* call-seq:
|
221
|
+
* Polyphony.backend_recv_loop(socket, max_len)
|
222
|
+
*
|
223
|
+
* Performs an infinite loop receiving data on the given socket. The loop terminates
|
224
|
+
* when the socket is closed.
|
225
|
+
*
|
226
|
+
* @param socket [Socket] socket to receive on
|
227
|
+
* @param maxlen [Integer] maximum bytes to read
|
228
|
+
*
|
229
|
+
* @return [void]
|
230
|
+
*/
|
231
|
+
|
232
|
+
VALUE Polyphony_backend_recv_loop(VALUE self, VALUE socket, VALUE maxlen) {
|
233
|
+
return Backend_recv_loop(BACKEND(), socket, maxlen);
|
75
234
|
}
|
76
235
|
|
77
|
-
|
78
|
-
|
236
|
+
/* call-seq:
|
237
|
+
* Polyphony.backend_recv_feed_loop(socket, receiver, method)
|
238
|
+
*
|
239
|
+
* Runs a feed loop, receiving data on the given socket, feeding it to the receiver
|
240
|
+
* with the given method, and passing the receiver's output to the given block.
|
241
|
+
* The loop terminates when EOF is encountered.
|
242
|
+
*
|
243
|
+
* @param socket [Socket] socket to receive on
|
244
|
+
* @param receiver [any] an object receiving the data
|
245
|
+
* @param method [Symbol] method used to feed the data to the receiver
|
246
|
+
* @yield [any] data passed to the given block
|
247
|
+
*
|
248
|
+
* @return [void]
|
249
|
+
*/
|
250
|
+
|
251
|
+
VALUE Polyphony_backend_recv_feed_loop(VALUE self, VALUE socket, VALUE receiver, VALUE method) {
|
252
|
+
return Backend_recv_feed_loop(BACKEND(), socket, receiver, method);
|
79
253
|
}
|
80
254
|
|
81
|
-
|
82
|
-
|
255
|
+
/* call-seq:
|
256
|
+
* Polyphony.backend_send(socket, msg, flags) -> bytes_sent
|
257
|
+
*
|
258
|
+
* Sends data on the given socket, returning the number of bytes sent.
|
259
|
+
*
|
260
|
+
* @param socket [Socket] socket to read from
|
261
|
+
* @param msg [String] data to be sent
|
262
|
+
* @param flags [Integer] Flags
|
263
|
+
*
|
264
|
+
* @return [Integer] number of bytes sent
|
265
|
+
*/
|
266
|
+
|
267
|
+
VALUE Polyphony_backend_send(VALUE self, VALUE socket, VALUE msg, VALUE flags) {
|
268
|
+
return Backend_send(BACKEND(), socket, msg, flags);
|
83
269
|
}
|
84
270
|
|
85
|
-
|
86
|
-
|
271
|
+
/* call-seq:
|
272
|
+
* Polyphony.backend_sendmsg(socket, msg, flags, dest_sockaddr, controls) -> bytes_sent
|
273
|
+
*
|
274
|
+
* Sends data on the given socket, returning the number of bytes sent.
|
275
|
+
*
|
276
|
+
* @param socket [Socket] socket to read from
|
277
|
+
* @param msg [String] data to be sent
|
278
|
+
* @param flags [Integer] Flags
|
279
|
+
* @param dest_sockaddr [any] Destination address
|
280
|
+
* @param controls [any] Control data
|
281
|
+
* @return [Integer] number of bytes sent
|
282
|
+
*/
|
283
|
+
|
284
|
+
VALUE Polyphony_backend_sendmsg(VALUE self, VALUE socket, VALUE msg, VALUE flags, VALUE dest_sockaddr, VALUE controls) {
|
285
|
+
return Backend_sendmsg(BACKEND(), socket, msg, flags, dest_sockaddr, controls);
|
87
286
|
}
|
88
287
|
|
89
|
-
|
90
|
-
|
288
|
+
/* call-seq:
|
289
|
+
* Polyphony.backend_sendv(socket, ary, flags) -> bytes_sent
|
290
|
+
*
|
291
|
+
* Sends multiple strings on the given socket, returning the number of bytes sent.
|
292
|
+
*
|
293
|
+
* @param socket [Socket] socket to read from
|
294
|
+
* @param ary [Array<String>] data to be sent
|
295
|
+
* @param flags [Integer] Flags
|
296
|
+
* @return [Integer] number of bytes sent
|
297
|
+
*/
|
298
|
+
|
299
|
+
VALUE Polyphony_backend_sendv(VALUE self, VALUE socket, VALUE ary, VALUE flags) {
|
300
|
+
return Backend_sendv(BACKEND(), socket, ary, flags);
|
91
301
|
}
|
92
302
|
|
303
|
+
/* call-seq:
|
304
|
+
* Polyphony.backend_sleep(duration)
|
305
|
+
*
|
306
|
+
* Sleeps for the given duration, yielding execution to other fibers.
|
307
|
+
*
|
308
|
+
* @param duration [Number] duration in seconds
|
309
|
+
* @return [void]
|
310
|
+
*/
|
311
|
+
|
93
312
|
VALUE Polyphony_backend_sleep(VALUE self, VALUE duration) {
|
94
313
|
return Backend_sleep(BACKEND(), duration);
|
95
314
|
}
|
96
315
|
|
316
|
+
/* call-seq:
|
317
|
+
* Polyphony.backend_splice(src, dest, maxlen) -> bytes_spliced
|
318
|
+
*
|
319
|
+
* Splices data from the given source to the given destination, returning the
|
320
|
+
* number of bytes spliced.
|
321
|
+
*
|
322
|
+
* @param src [IO] source
|
323
|
+
* @param dest [IO] destination
|
324
|
+
* @param maxlen [Integer] Maximum bytes to splice
|
325
|
+
* @return [Integer] number of bytes spliced
|
326
|
+
*/
|
327
|
+
|
97
328
|
VALUE Polyphony_backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
98
329
|
return Backend_splice(BACKEND(), src, dest, maxlen);
|
99
330
|
}
|
100
331
|
|
101
332
|
#ifdef POLYPHONY_BACKEND_LIBURING
|
333
|
+
/* @!visibility private */
|
334
|
+
|
102
335
|
VALUE Polyphony_backend_double_splice(VALUE self, VALUE src, VALUE dest) {
|
103
336
|
return Backend_double_splice(BACKEND(), src, dest);
|
104
337
|
}
|
105
338
|
#endif
|
106
339
|
|
107
340
|
#ifdef POLYPHONY_LINUX
|
341
|
+
/* @!visibility private */
|
342
|
+
|
108
343
|
VALUE Polyphony_backend_tee(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
|
109
344
|
return Backend_tee(BACKEND(), src, dest, chunksize);
|
110
345
|
}
|
111
346
|
#endif
|
112
347
|
|
348
|
+
/* call-seq:
|
349
|
+
* Polyphony.backend_timeout(duration) { ... }
|
350
|
+
* Polyphony.backend_timeout(duration, exception_class) { ... }
|
351
|
+
*
|
352
|
+
* Runs the given block, raising an exception if the block has not finished
|
353
|
+
* running before a timeout has elapsed, using the given duration. If an
|
354
|
+
* exception class is not given, a TimeoutError is raised.
|
355
|
+
*
|
356
|
+
*/
|
357
|
+
|
113
358
|
VALUE Polyphony_backend_timeout(int argc,VALUE *argv, VALUE self) {
|
114
359
|
return Backend_timeout(argc, argv, BACKEND());
|
115
360
|
}
|
116
361
|
|
362
|
+
/* call-seq:
|
363
|
+
* Polyphony.backend_timer_loop(interval) { ... }
|
364
|
+
*
|
365
|
+
* Runs an infinite loop that calls the given block at the specified time interval.
|
366
|
+
*
|
367
|
+
* @param interval [Number] interval in seconds
|
368
|
+
* @yield [] code to run
|
369
|
+
* @return [void]
|
370
|
+
*/
|
371
|
+
|
117
372
|
VALUE Polyphony_backend_timer_loop(VALUE self, VALUE interval) {
|
118
373
|
return Backend_timer_loop(BACKEND(), interval);
|
119
374
|
}
|
120
375
|
|
376
|
+
/* call-seq:
|
377
|
+
* Polyphony.backend_wait_event(raise)
|
378
|
+
*
|
379
|
+
* For for the current fiber to be rescheduled, resuming the fiber with its
|
380
|
+
* resumed value. If raise is true and the resumed value is an exception, an
|
381
|
+
* exception will be raised.
|
382
|
+
*
|
383
|
+
* @param raise [boolean]
|
384
|
+
* @return [any] resumed value
|
385
|
+
*/
|
386
|
+
|
121
387
|
VALUE Polyphony_backend_wait_event(VALUE self, VALUE raise) {
|
122
388
|
return Backend_wait_event(BACKEND(), raise);
|
123
389
|
}
|
124
390
|
|
391
|
+
/* call-seq:
|
392
|
+
* Polyphony.backend_wait_io(io, read_or_write)
|
393
|
+
*
|
394
|
+
* Waits for the given IO to be readable or writeable, according to the
|
395
|
+
* read_or_write parameter.
|
396
|
+
*
|
397
|
+
* @param io [IO]
|
398
|
+
* @param write [boolean] false for read, true for write
|
399
|
+
* @return [void]
|
400
|
+
*/
|
401
|
+
|
125
402
|
VALUE Polyphony_backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
126
403
|
return Backend_wait_io(BACKEND(), io, write);
|
127
404
|
}
|
128
405
|
|
406
|
+
/* call-seq:
|
407
|
+
* Polyphony.backend_wait_pid(pid) -> exit code
|
408
|
+
*
|
409
|
+
* Waits for the given process to terminate, returning its exit code.
|
410
|
+
*
|
411
|
+
* @param pid [Integer] pid
|
412
|
+
* @return [Integer] exit code
|
413
|
+
*/
|
414
|
+
|
129
415
|
VALUE Polyphony_backend_waitpid(VALUE self, VALUE pid) {
|
130
416
|
return Backend_waitpid(BACKEND(), pid);
|
131
417
|
}
|
132
418
|
|
419
|
+
/* call-seq:
|
420
|
+
* Polyphony.backend_write(io, data, ...) -> bytes_written
|
421
|
+
*
|
422
|
+
* Writes one or more strings to the given io, returning the total number of
|
423
|
+
* bytes written.
|
424
|
+
*/
|
425
|
+
|
133
426
|
VALUE Polyphony_backend_write(int argc, VALUE *argv, VALUE self) {
|
134
427
|
return Backend_write_m(argc, argv, BACKEND());
|
135
428
|
}
|
136
429
|
|
430
|
+
/* @!visibility private */
|
431
|
+
|
137
432
|
VALUE Polyphony_with_raw_buffer(VALUE self, VALUE size) {
|
138
433
|
struct buffer_spec buffer_spec;
|
139
434
|
buffer_spec.len = FIX2INT(size);
|
@@ -146,6 +441,8 @@ VALUE Polyphony_with_raw_buffer(VALUE self, VALUE size) {
|
|
146
441
|
return return_value;
|
147
442
|
}
|
148
443
|
|
444
|
+
/* @!visibility private */
|
445
|
+
|
149
446
|
VALUE Polyphony_raw_buffer_get(int argc, VALUE *argv, VALUE self) {
|
150
447
|
VALUE buf = Qnil;
|
151
448
|
VALUE len = Qnil;
|
@@ -158,6 +455,8 @@ VALUE Polyphony_raw_buffer_get(int argc, VALUE *argv, VALUE self) {
|
|
158
455
|
return rb_utf8_str_new((char *)buffer_spec->ptr, length);
|
159
456
|
}
|
160
457
|
|
458
|
+
/* @!visibility private */
|
459
|
+
|
161
460
|
VALUE Polyphony_raw_buffer_set(VALUE self, VALUE buffer, VALUE str) {
|
162
461
|
struct buffer_spec *buffer_spec = FIX2PTR(buffer);
|
163
462
|
int len = RSTRING_LEN(str);
|
@@ -169,6 +468,8 @@ VALUE Polyphony_raw_buffer_set(VALUE self, VALUE buffer, VALUE str) {
|
|
169
468
|
return self;
|
170
469
|
}
|
171
470
|
|
471
|
+
/* @!visibility private */
|
472
|
+
|
172
473
|
VALUE Polyphony_raw_buffer_size(VALUE self, VALUE buffer) {
|
173
474
|
struct buffer_spec *buffer_spec = FIX2PTR(buffer);
|
174
475
|
return INT2FIX(buffer_spec->len);
|
@@ -186,6 +487,12 @@ void Init_Polyphony(void) {
|
|
186
487
|
rb_define_singleton_method(mPolyphony, "backend_accept_loop", Polyphony_backend_accept_loop, 2);
|
187
488
|
rb_define_singleton_method(mPolyphony, "backend_connect", Polyphony_backend_connect, 3);
|
188
489
|
rb_define_singleton_method(mPolyphony, "backend_feed_loop", Polyphony_backend_feed_loop, 3);
|
490
|
+
|
491
|
+
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
492
|
+
rb_define_singleton_method(mPolyphony, "backend_multishot_accept", Polyphony_backend_multishot_accept, 1);
|
493
|
+
#endif
|
494
|
+
|
495
|
+
|
189
496
|
rb_define_singleton_method(mPolyphony, "backend_read", Polyphony_backend_read, 5);
|
190
497
|
rb_define_singleton_method(mPolyphony, "backend_read_loop", Polyphony_backend_read_loop, 2);
|
191
498
|
rb_define_singleton_method(mPolyphony, "backend_recv", Polyphony_backend_recv, 4);
|
@@ -223,25 +530,32 @@ void Init_Polyphony(void) {
|
|
223
530
|
rb_define_global_function("snooze", Polyphony_snooze, 0);
|
224
531
|
rb_define_global_function("suspend", Polyphony_suspend, 0);
|
225
532
|
|
533
|
+
/*
|
534
|
+
* Document-class: Polyphony::TimeoutException
|
535
|
+
*
|
536
|
+
* An exception raised on timeout.
|
537
|
+
*/
|
538
|
+
|
226
539
|
cTimeoutException = rb_define_class_under(mPolyphony, "TimeoutException", rb_eException);
|
227
540
|
|
228
|
-
ID_call
|
229
|
-
ID_caller
|
230
|
-
ID_clear
|
231
|
-
ID_each
|
232
|
-
ID_inspect
|
233
|
-
ID_invoke
|
234
|
-
ID_ivar_blocking_mode
|
235
|
-
ID_ivar_io
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
541
|
+
ID_call = rb_intern("call");
|
542
|
+
ID_caller = rb_intern("caller");
|
543
|
+
ID_clear = rb_intern("clear");
|
544
|
+
ID_each = rb_intern("each");
|
545
|
+
ID_inspect = rb_intern("inspect");
|
546
|
+
ID_invoke = rb_intern("invoke");
|
547
|
+
ID_ivar_blocking_mode = rb_intern("@blocking_mode");
|
548
|
+
ID_ivar_io = rb_intern("@io");
|
549
|
+
ID_ivar_multishot_accept_queue = rb_intern("@multishot_accept_queue");
|
550
|
+
ID_ivar_parked = rb_intern("@parked");
|
551
|
+
ID_ivar_runnable = rb_intern("@runnable");
|
552
|
+
ID_ivar_running = rb_intern("@running");
|
553
|
+
ID_ivar_thread = rb_intern("@thread");
|
554
|
+
ID_new = rb_intern("new");
|
555
|
+
ID_raise = rb_intern("raise");
|
556
|
+
ID_signal = rb_intern("signal");
|
557
|
+
ID_size = rb_intern("size");
|
558
|
+
ID_switch_fiber = rb_intern("switch_fiber");
|
559
|
+
ID_to_s = rb_intern("to_s");
|
560
|
+
ID_transfer = rb_intern("transfer");
|
247
561
|
}
|
data/ext/polyphony/polyphony.h
CHANGED
@@ -14,8 +14,9 @@
|
|
14
14
|
// exceptions
|
15
15
|
#define TEST_EXCEPTION(ret) (rb_obj_is_kind_of(ret, rb_eException) == Qtrue)
|
16
16
|
#define RAISE_EXCEPTION(e) rb_funcall(e, ID_invoke, 0);
|
17
|
-
#define
|
18
|
-
#define
|
17
|
+
#define IS_EXCEPTION(o) (rb_obj_is_kind_of(o, rb_eException) == Qtrue)
|
18
|
+
#define RAISE_IF_EXCEPTION(o) if (IS_EXCEPTION(o)) { RAISE_EXCEPTION(o); }
|
19
|
+
#define RAISE_IF_NOT_NIL(o) if (o != Qnil) { RAISE_EXCEPTION(o); }
|
19
20
|
|
20
21
|
// Fiber#transfer
|
21
22
|
#if HAVE_RB_FIBER_TRANSFER
|
@@ -44,6 +45,7 @@ extern ID ID_invoke;
|
|
44
45
|
extern ID ID_ivar_backend;
|
45
46
|
extern ID ID_ivar_blocking_mode;
|
46
47
|
extern ID ID_ivar_io;
|
48
|
+
extern ID ID_ivar_multishot_accept_queue;
|
47
49
|
extern ID ID_ivar_parked;
|
48
50
|
extern ID ID_ivar_runnable;
|
49
51
|
extern ID ID_ivar_running;
|
@@ -97,6 +99,11 @@ VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class);
|
|
97
99
|
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class);
|
98
100
|
VALUE Backend_connect(VALUE self, VALUE io, VALUE addr, VALUE port);
|
99
101
|
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method);
|
102
|
+
|
103
|
+
#ifdef HAVE_IO_URING_PREP_MULTISHOT_ACCEPT
|
104
|
+
VALUE Backend_multishot_accept(VALUE self, VALUE io);
|
105
|
+
#endif
|
106
|
+
|
100
107
|
VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof, VALUE pos);
|
101
108
|
VALUE Backend_read_loop(VALUE self, VALUE io, VALUE maxlen);
|
102
109
|
VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length, VALUE pos);
|