polyphony 0.47.4 → 0.49.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/CHANGELOG.md +321 -296
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +38 -29
- data/examples/core/supervisor.rb +3 -3
- data/examples/core/worker-thread.rb +3 -4
- data/examples/io/tcp_proxy.rb +32 -0
- data/examples/performance/line_splitting.rb +34 -0
- data/examples/performance/loop.rb +32 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -0
- data/ext/polyphony/backend_common.h +2 -22
- data/ext/polyphony/backend_io_uring.c +38 -78
- data/ext/polyphony/backend_libev.c +22 -67
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +5 -4
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/thread.c +9 -28
- data/lib/polyphony.rb +2 -1
- data/lib/polyphony/adapters/postgres.rb +3 -3
- data/lib/polyphony/adapters/process.rb +2 -0
- data/lib/polyphony/core/global_api.rb +14 -2
- data/lib/polyphony/core/thread_pool.rb +3 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +72 -0
- data/lib/polyphony/extensions/fiber.rb +32 -8
- data/lib/polyphony/extensions/io.rb +8 -14
- data/lib/polyphony/extensions/openssl.rb +4 -4
- data/lib/polyphony/extensions/socket.rb +13 -10
- data/lib/polyphony/net.rb +3 -6
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +1 -0
- data/test/test_backend.rb +1 -1
- data/test/test_fiber.rb +64 -1
- data/test/test_global_api.rb +30 -0
- data/test/test_io.rb +26 -0
- data/test/test_socket.rb +32 -6
- data/test/test_supervise.rb +2 -1
- data/test/test_timer.rb +124 -0
- metadata +8 -4
- data/ext/polyphony/backend.h +0 -26
data/Gemfile.lock
CHANGED
data/LICENSE
CHANGED
data/TODO.md
CHANGED
@@ -1,49 +1,58 @@
|
|
1
|
-
-
|
1
|
+
- Check segfault when resetting a `cancel_after` timeout lots of times at very high rate
|
2
|
+
- Check why `throttled_loop` inside of `move_on_after` fails to stop
|
2
3
|
|
3
|
-
|
4
|
-
- Two exceptions for stopping fibers:
|
5
|
-
- `Polyphony::GracefulShutdown` - graceful shutdown
|
6
|
-
- `Polyphony::Terminate` - ungraceful shutdown
|
7
|
-
- Fiber API:
|
8
|
-
- `Fiber#shutdown_children` - graceful shutdown of all children
|
9
|
-
- `Fiber#terminate_children` - ungraceful shutdown of all children
|
4
|
+
- Override stock `::SizedQueue` impl with Queue with capacity
|
10
5
|
|
11
|
-
|
12
|
-
- Returns false unless a `Polyphony::GracefulShutdown` was raised
|
13
|
-
- Override `Polyphony::Terminate#invoke` to reset the `@graceful_shutdown` fiber
|
14
|
-
flag
|
6
|
+
- Add support for `break` and `StopIteration` in all loops (with tests)
|
15
7
|
|
16
|
-
|
8
|
+
- Change `IO#gets` to use `String#split` to cut into lines, much faster (see
|
9
|
+
examples/performance/line_splitting.rb)
|
10
|
+
|
11
|
+
- More tight loops
|
12
|
+
- `IO#gets_loop`, `Socket#gets_loop`, `OpenSSL::Socket#gets_loop` (medium effort)
|
13
|
+
- `Fiber#receive_loop` (very little effort, should be implemented in C)
|
17
14
|
|
18
|
-
```ruby
|
19
|
-
spin do
|
20
|
-
loop { do_some_stuff }
|
21
|
-
ensure
|
22
|
-
return unless Fiber.current.graceful_shutdown?
|
23
15
|
|
24
|
-
|
16
|
+
- Add `Backend#splice`, `Backend#splice_loop` for implementing stuff like proxying:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
def two_way_proxy(socket1, socket2)
|
20
|
+
backend = Thread.current.backend
|
21
|
+
f1 = spin { backend.splice_loop(socket1, socket2) }
|
22
|
+
f2 = spin { backend.splice_loop(socket2, socket1) }
|
23
|
+
Fiber.await(f1, f2)
|
25
24
|
end
|
26
25
|
```
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
-
|
33
|
-
-
|
34
|
-
|
27
|
+
- Graceful shutdown again:
|
28
|
+
- What happens to children when doing a graceful shutdown?
|
29
|
+
- What are the implications of passing graceful shutdown flag to children?
|
30
|
+
- What about errors while doing a graceful shutdown?
|
31
|
+
- What about graceful restarts?
|
32
|
+
- Some interesting discussions:
|
33
|
+
- https://trio.discourse.group/search?q=graceful%20shutdown
|
34
|
+
- https://github.com/python-trio/trio/issues/147
|
35
|
+
- https://github.com/python-trio/trio/issues/143
|
36
|
+
- https://trio.discourse.group/t/graceful-shutdown/93/2
|
37
|
+
- https://250bpm.com/blog:146/
|
38
|
+
- https://www.rodrigoaraujo.me/posts/golang-pattern-graceful-shutdown-of-concurrent-events/
|
39
|
+
- https://github.com/tj/go-gracefully
|
40
|
+
- `Fiber#finalize_children` should pass graceful shutdown flag to children
|
41
|
+
- A good use case is an HTTP server that on graceful shutdown:
|
42
|
+
- stops listening
|
43
|
+
- waits for all ongoing requests to finish, optionally with a timeout
|
35
44
|
|
36
45
|
## Roadmap for Polyphony 1.0
|
37
46
|
|
38
47
|
- check integration with rb-inotify
|
39
48
|
|
40
|
-
-
|
49
|
+
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
50
|
+
inconsistent behaviour (see supervisor example).
|
51
|
+
|
41
52
|
- Add test that mimics the original design for Monocrono:
|
42
53
|
- 256 fibers each waiting for a message
|
43
54
|
- When message received do some blocking work using a `ThreadPool`
|
44
55
|
- Send messages, collect responses, check for correctness
|
45
|
-
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
46
|
-
inconsistent behaviour (see supervisor example).
|
47
56
|
|
48
57
|
- io_uring
|
49
58
|
- Use playground.c to find out why we when submitting and waiting for
|
data/examples/core/supervisor.rb
CHANGED
@@ -9,9 +9,9 @@ def my_sleep(t)
|
|
9
9
|
puts "#{t} done"
|
10
10
|
end
|
11
11
|
|
12
|
-
spin { my_sleep(1) }
|
13
|
-
spin { my_sleep(2) }
|
14
|
-
spin { my_sleep(3) }
|
12
|
+
spin { my_sleep(0.1) }
|
13
|
+
spin { my_sleep(0.2) }
|
14
|
+
spin { my_sleep(0.3) }
|
15
15
|
spin { puts "fiber count: #{Fiber.current.children.count}" }
|
16
16
|
snooze
|
17
17
|
|
@@ -13,11 +13,9 @@ end
|
|
13
13
|
$worker = Thread.new do
|
14
14
|
Fiber.current.tag = :worker
|
15
15
|
loop do
|
16
|
-
client, block = receive
|
16
|
+
(client, block) = receive
|
17
17
|
do_work(client, &block)
|
18
18
|
end
|
19
|
-
rescue Exception => e
|
20
|
-
p e
|
21
19
|
end
|
22
20
|
|
23
21
|
def process(&block)
|
@@ -27,4 +25,5 @@ end
|
|
27
25
|
|
28
26
|
sleep 0.1
|
29
27
|
|
30
|
-
p process { 1 + 1 }
|
28
|
+
p process { 1 + 1 }
|
29
|
+
p process { 42 ** 2 }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
|
6
|
+
server1 = TCPServer.open('127.0.0.1', 1234)
|
7
|
+
server2 = TCPServer.open('127.0.0.1', 1235)
|
8
|
+
|
9
|
+
puts "Pid: #{Process.pid}"
|
10
|
+
puts 'Proxying port 1234 => port 1235'
|
11
|
+
|
12
|
+
client1 = client2 = nil
|
13
|
+
|
14
|
+
f1 = spin {
|
15
|
+
client1 = server1.accept
|
16
|
+
loop do
|
17
|
+
if client2
|
18
|
+
Thread.current.backend.splice_loop(client1, client2)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
f2 = spin {
|
24
|
+
client2 = server2.accept
|
25
|
+
loop do
|
26
|
+
if client1
|
27
|
+
Thread.current.backend.splice_loop(client2, client1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
}
|
31
|
+
|
32
|
+
Fiber.await(f1, f2)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "benchmark/ips"
|
4
|
+
|
5
|
+
def slice
|
6
|
+
str = ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40)
|
7
|
+
lines = []
|
8
|
+
while true
|
9
|
+
idx = str.index("\n")
|
10
|
+
break unless idx
|
11
|
+
|
12
|
+
lines << str.slice!(0, idx + 1)
|
13
|
+
end
|
14
|
+
raise unless lines.size == 4
|
15
|
+
raise unless str == ('*' * 40)
|
16
|
+
end
|
17
|
+
|
18
|
+
def split
|
19
|
+
str = ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40) + "\n" + ('*' * 40)
|
20
|
+
lines = str.split("\n")
|
21
|
+
if str[-1] == "\n"
|
22
|
+
str = ''
|
23
|
+
else
|
24
|
+
str = lines.pop
|
25
|
+
end
|
26
|
+
raise unless lines.size == 4
|
27
|
+
raise unless str == ('*' * 40)
|
28
|
+
end
|
29
|
+
|
30
|
+
Benchmark.ips do |x|
|
31
|
+
x.report("slice") { slice }
|
32
|
+
x.report("split") { split }
|
33
|
+
x.compare!
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
LIMIT = 1_000_0
|
6
|
+
|
7
|
+
def do_while
|
8
|
+
i = 0
|
9
|
+
while true
|
10
|
+
i += 1
|
11
|
+
break if i == LIMIT
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def do_loop
|
16
|
+
i = 0
|
17
|
+
loop do
|
18
|
+
i += 1
|
19
|
+
break if i == LIMIT
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
GC.disable
|
24
|
+
Benchmark.bm do |x|
|
25
|
+
x.report('while') do
|
26
|
+
LIMIT.times { do_while }
|
27
|
+
end
|
28
|
+
x.report('loop') do
|
29
|
+
LIMIT.times { do_loop }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -29,6 +29,12 @@ end
|
|
29
29
|
server = TCPServer.open('0.0.0.0', 1234)
|
30
30
|
puts "pid #{Process.pid} Polyphony (#{Thread.current.backend.kind}) listening on port 1234"
|
31
31
|
|
32
|
+
spin_loop(interval: 10) do
|
33
|
+
p Thread.current.fiber_scheduling_stats
|
34
|
+
end
|
35
|
+
|
36
|
+
GC.disable
|
37
|
+
|
32
38
|
server.accept_loop do |c|
|
33
39
|
spin { handle_client(c) }
|
34
40
|
end
|
@@ -3,26 +3,6 @@
|
|
3
3
|
#include "ruby.h"
|
4
4
|
#include "ruby/io.h"
|
5
5
|
|
6
|
-
VALUE cTCPSocket;
|
7
|
-
VALUE cTCPServer;
|
8
|
-
VALUE cUNIXSocket;
|
9
|
-
VALUE cUNIXServer;
|
10
|
-
|
11
|
-
void Init_SocketClasses() {
|
12
|
-
rb_require("socket");
|
13
|
-
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
14
|
-
cTCPServer = rb_const_get(rb_cObject, rb_intern("TCPServer"));
|
15
|
-
cUNIXSocket = rb_const_get(rb_cObject, rb_intern("UNIXSocket"));
|
16
|
-
cUNIXServer = rb_const_get(rb_cObject, rb_intern("UNIXServer"));
|
17
|
-
}
|
18
|
-
|
19
|
-
VALUE ConnectionSocketClass(VALUE server) {
|
20
|
-
if (RTEST(rb_obj_is_kind_of(server, cTCPServer))) return cTCPSocket;
|
21
|
-
if (RTEST(rb_obj_is_kind_of(server, cUNIXServer))) return cUNIXSocket;
|
22
|
-
|
23
|
-
rb_raise(rb_eRuntimeError, "Invalid server class");
|
24
|
-
}
|
25
|
-
|
26
6
|
//////////////////////////////////////////////////////////////////////
|
27
7
|
//////////////////////////////////////////////////////////////////////
|
28
8
|
// the following is copied verbatim from the Ruby source code (io.c)
|
@@ -90,9 +70,9 @@ inline VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
|
|
90
70
|
|
91
71
|
inline VALUE backend_await(Backend_t *backend) {
|
92
72
|
VALUE ret;
|
93
|
-
backend->
|
73
|
+
backend->pending_count++;
|
94
74
|
ret = Thread_switch_fiber(rb_thread_current());
|
95
|
-
backend->
|
75
|
+
backend->pending_count--;
|
96
76
|
RB_GC_GUARD(ret);
|
97
77
|
return ret;
|
98
78
|
}
|
@@ -30,11 +30,14 @@ static int pidfd_open(pid_t pid, unsigned int flags) {
|
|
30
30
|
VALUE SYM_io_uring;
|
31
31
|
|
32
32
|
typedef struct Backend_t {
|
33
|
+
// common fields
|
34
|
+
unsigned int currently_polling;
|
35
|
+
unsigned int pending_count;
|
36
|
+
unsigned int poll_no_wait_count;
|
37
|
+
|
38
|
+
// implementation-specific fields
|
33
39
|
struct io_uring ring;
|
34
40
|
op_context_store_t store;
|
35
|
-
int waiting_for_cqe;
|
36
|
-
unsigned int ref_count;
|
37
|
-
unsigned int run_no_wait_count;
|
38
41
|
unsigned int pending_sqes;
|
39
42
|
unsigned int prepared_limit;
|
40
43
|
int event_fd;
|
@@ -65,11 +68,11 @@ static VALUE Backend_initialize(VALUE self) {
|
|
65
68
|
Backend_t *backend;
|
66
69
|
GetBackend(self, backend);
|
67
70
|
|
68
|
-
backend->
|
69
|
-
backend->
|
70
|
-
backend->
|
71
|
+
backend->currently_polling = 0;
|
72
|
+
backend->pending_count = 0;
|
73
|
+
backend->poll_no_wait_count = 0;
|
71
74
|
backend->pending_sqes = 0;
|
72
|
-
backend->prepared_limit =
|
75
|
+
backend->prepared_limit = 2048;
|
73
76
|
|
74
77
|
context_store_initialize(&backend->store);
|
75
78
|
io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
@@ -95,46 +98,19 @@ VALUE Backend_post_fork(VALUE self) {
|
|
95
98
|
io_uring_queue_exit(&backend->ring);
|
96
99
|
io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
97
100
|
context_store_free(&backend->store);
|
98
|
-
backend->
|
99
|
-
backend->
|
100
|
-
backend->
|
101
|
+
backend->currently_polling = 0;
|
102
|
+
backend->pending_count = 0;
|
103
|
+
backend->poll_no_wait_count = 0;
|
101
104
|
backend->pending_sqes = 0;
|
102
105
|
|
103
106
|
return self;
|
104
107
|
}
|
105
108
|
|
106
|
-
|
107
|
-
Backend_t *backend;
|
108
|
-
GetBackend(self, backend);
|
109
|
-
|
110
|
-
backend->ref_count++;
|
111
|
-
return self;
|
112
|
-
}
|
113
|
-
|
114
|
-
VALUE Backend_unref(VALUE self) {
|
115
|
-
Backend_t *backend;
|
116
|
-
GetBackend(self, backend);
|
117
|
-
|
118
|
-
backend->ref_count--;
|
119
|
-
return self;
|
120
|
-
}
|
121
|
-
|
122
|
-
int Backend_ref_count(VALUE self) {
|
123
|
-
Backend_t *backend;
|
124
|
-
GetBackend(self, backend);
|
125
|
-
|
126
|
-
return backend->ref_count;
|
127
|
-
}
|
128
|
-
|
129
|
-
void Backend_reset_ref_count(VALUE self) {
|
109
|
+
unsigned int Backend_pending_count(VALUE self) {
|
130
110
|
Backend_t *backend;
|
131
111
|
GetBackend(self, backend);
|
132
112
|
|
133
|
-
backend->
|
134
|
-
}
|
135
|
-
|
136
|
-
VALUE Backend_pending_count(VALUE self) {
|
137
|
-
return INT2NUM(0);
|
113
|
+
return backend->pending_count;
|
138
114
|
}
|
139
115
|
|
140
116
|
typedef struct poll_context {
|
@@ -158,7 +134,7 @@ static inline bool cq_ring_needs_flush(struct io_uring *ring) {
|
|
158
134
|
|
159
135
|
void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *backend) {
|
160
136
|
op_context_t *ctx = io_uring_cqe_get_data(cqe);
|
161
|
-
if (ctx
|
137
|
+
if (!ctx) return;
|
162
138
|
|
163
139
|
ctx->result = cqe->res;
|
164
140
|
|
@@ -211,9 +187,9 @@ void io_uring_backend_poll(Backend_t *backend) {
|
|
211
187
|
io_uring_submit(&backend->ring);
|
212
188
|
}
|
213
189
|
|
214
|
-
backend->
|
190
|
+
backend->currently_polling = 1;
|
215
191
|
rb_thread_call_without_gvl(io_uring_backend_poll_without_gvl, (void *)&poll_ctx, RUBY_UBF_IO, 0);
|
216
|
-
backend->
|
192
|
+
backend->currently_polling = 0;
|
217
193
|
if (poll_ctx.result < 0) return;
|
218
194
|
|
219
195
|
io_uring_backend_handle_completion(poll_ctx.cqe, backend);
|
@@ -226,14 +202,14 @@ VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue
|
|
226
202
|
GetBackend(self, backend);
|
227
203
|
|
228
204
|
if (is_nowait) {
|
229
|
-
backend->
|
230
|
-
if (backend->
|
205
|
+
backend->poll_no_wait_count++;
|
206
|
+
if (backend->poll_no_wait_count < 10) return self;
|
231
207
|
|
232
208
|
long runnable_count = Runqueue_len(runqueue);
|
233
|
-
if (backend->
|
209
|
+
if (backend->poll_no_wait_count < runnable_count) return self;
|
234
210
|
}
|
235
211
|
|
236
|
-
backend->
|
212
|
+
backend->poll_no_wait_count = 0;
|
237
213
|
|
238
214
|
if (is_nowait && backend->pending_sqes) {
|
239
215
|
backend->pending_sqes = 0;
|
@@ -252,7 +228,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
252
228
|
Backend_t *backend;
|
253
229
|
GetBackend(self, backend);
|
254
230
|
|
255
|
-
if (backend->
|
231
|
+
if (backend->currently_polling) {
|
256
232
|
// Since we're currently blocking while waiting for a completion, we add a
|
257
233
|
// NOP which would cause the io_uring_enter syscall to return
|
258
234
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
@@ -284,12 +260,12 @@ int io_uring_backend_defer_submit_and_await(
|
|
284
260
|
VALUE switchpoint_result = Qnil;
|
285
261
|
|
286
262
|
io_uring_sqe_set_data(sqe, ctx);
|
287
|
-
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
263
|
+
// io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
288
264
|
io_uring_backend_defer_submit(backend);
|
289
265
|
|
290
|
-
backend->
|
266
|
+
backend->pending_count++;
|
291
267
|
switchpoint_result = backend_await(backend);
|
292
|
-
backend->
|
268
|
+
backend->pending_count--;
|
293
269
|
|
294
270
|
if (!ctx->completed) {
|
295
271
|
ctx->result = -ECANCELED;
|
@@ -351,7 +327,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
351
327
|
|
352
328
|
if (result < 0)
|
353
329
|
rb_syserr_fail(-result, strerror(-result));
|
354
|
-
else if (result
|
330
|
+
else if (!result)
|
355
331
|
break; // EOF
|
356
332
|
else {
|
357
333
|
total += result;
|
@@ -373,7 +349,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
373
349
|
io_set_read_length(str, total, shrinkable);
|
374
350
|
io_enc_str(str, fptr);
|
375
351
|
|
376
|
-
if (total
|
352
|
+
if (!total) return Qnil;
|
377
353
|
|
378
354
|
return str;
|
379
355
|
}
|
@@ -410,7 +386,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
410
386
|
|
411
387
|
if (result < 0)
|
412
388
|
rb_syserr_fail(-result, strerror(-result));
|
413
|
-
else if (result
|
389
|
+
else if (!result)
|
414
390
|
break; // EOF
|
415
391
|
else {
|
416
392
|
total = result;
|
@@ -581,7 +557,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
581
557
|
io_set_read_length(str, total, shrinkable);
|
582
558
|
io_enc_str(str, fptr);
|
583
559
|
|
584
|
-
if (total
|
560
|
+
if (!total) return Qnil;
|
585
561
|
|
586
562
|
return str;
|
587
563
|
}
|
@@ -618,7 +594,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io) {
|
|
618
594
|
|
619
595
|
if (result < 0)
|
620
596
|
rb_syserr_fail(-result, strerror(-result));
|
621
|
-
else if (result
|
597
|
+
else if (!result)
|
622
598
|
break; // EOF
|
623
599
|
else {
|
624
600
|
total = result;
|
@@ -668,12 +644,11 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str) {
|
|
668
644
|
return INT2NUM(len);
|
669
645
|
}
|
670
646
|
|
671
|
-
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, int loop) {
|
647
|
+
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
|
672
648
|
rb_io_t *fptr;
|
673
649
|
struct sockaddr addr;
|
674
650
|
socklen_t len = (socklen_t)sizeof addr;
|
675
651
|
VALUE socket = Qnil;
|
676
|
-
VALUE socket_class = ConnectionSocketClass(server_socket);
|
677
652
|
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
678
653
|
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
679
654
|
|
@@ -718,16 +693,16 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, int loop)
|
|
718
693
|
return Qnil;
|
719
694
|
}
|
720
695
|
|
721
|
-
VALUE Backend_accept(VALUE self, VALUE
|
696
|
+
VALUE Backend_accept(VALUE self, VALUE server_socket, VALUE socket_class) {
|
722
697
|
Backend_t *backend;
|
723
698
|
GetBackend(self, backend);
|
724
|
-
return io_uring_backend_accept(backend,
|
699
|
+
return io_uring_backend_accept(backend, server_socket, socket_class, 0);
|
725
700
|
}
|
726
701
|
|
727
|
-
VALUE Backend_accept_loop(VALUE self, VALUE
|
702
|
+
VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
728
703
|
Backend_t *backend;
|
729
704
|
GetBackend(self, backend);
|
730
|
-
io_uring_backend_accept(backend,
|
705
|
+
io_uring_backend_accept(backend, server_socket, socket_class, 1);
|
731
706
|
return self;
|
732
707
|
}
|
733
708
|
|
@@ -945,18 +920,12 @@ VALUE Backend_kind(VALUE self) {
|
|
945
920
|
}
|
946
921
|
|
947
922
|
void Init_Backend() {
|
948
|
-
Init_SocketClasses();
|
949
|
-
|
950
923
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
|
951
924
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
952
925
|
|
953
926
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
954
927
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
955
928
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
956
|
-
rb_define_method(cBackend, "pending_count", Backend_pending_count, 0);
|
957
|
-
|
958
|
-
rb_define_method(cBackend, "ref", Backend_ref, 0);
|
959
|
-
rb_define_method(cBackend, "unref", Backend_unref, 0);
|
960
929
|
|
961
930
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
962
931
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
@@ -967,8 +936,8 @@ void Init_Backend() {
|
|
967
936
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
968
937
|
rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 1);
|
969
938
|
rb_define_method(cBackend, "send", Backend_send, 2);
|
970
|
-
rb_define_method(cBackend, "accept", Backend_accept,
|
971
|
-
rb_define_method(cBackend, "accept_loop", Backend_accept_loop,
|
939
|
+
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
940
|
+
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
972
941
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
973
942
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
974
943
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
@@ -980,15 +949,6 @@ void Init_Backend() {
|
|
980
949
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
981
950
|
|
982
951
|
SYM_io_uring = ID2SYM(rb_intern("io_uring"));
|
983
|
-
|
984
|
-
__BACKEND__.pending_count = Backend_pending_count;
|
985
|
-
__BACKEND__.poll = Backend_poll;
|
986
|
-
__BACKEND__.ref = Backend_ref;
|
987
|
-
__BACKEND__.ref_count = Backend_ref_count;
|
988
|
-
__BACKEND__.reset_ref_count = Backend_reset_ref_count;
|
989
|
-
__BACKEND__.unref = Backend_unref;
|
990
|
-
__BACKEND__.wait_event = Backend_wait_event;
|
991
|
-
__BACKEND__.wakeup = Backend_wakeup;
|
992
952
|
}
|
993
953
|
|
994
954
|
#endif // POLYPHONY_BACKEND_LIBURING
|