polyphony 0.99 → 0.99.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.
- 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);
|