polyphony 0.47.3 → 0.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +318 -295
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +40 -27
- 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/io/unix_socket.rb +26 -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 -2
- data/ext/polyphony/backend_io_uring.c +42 -83
- data/ext/polyphony/backend_libev.c +32 -77
- 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 +1 -0
- data/lib/polyphony/adapters/postgres.rb +3 -3
- 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 +68 -16
- 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 +122 -0
- metadata +9 -4
- data/ext/polyphony/backend.h +0 -26
data/Gemfile.lock
CHANGED
data/LICENSE
CHANGED
data/TODO.md
CHANGED
@@ -1,44 +1,57 @@
|
|
1
|
-
|
1
|
+
- Check segfault when doing lots of `cancel_after` calls
|
2
2
|
|
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
|
3
|
+
- Override stock `SizedQueue` impl with Queue with capacity
|
10
4
|
|
11
|
-
- Add `
|
12
|
-
- Returns false unless a `Polyphony::GracefulShutdown` was raised
|
13
|
-
- Override `Polyphony::Terminate#invoke` to reset the `@graceful_shutdown` fiber
|
14
|
-
flag
|
5
|
+
- Add support for `break` and `StopIteration` in all loops (with tests)
|
15
6
|
|
16
|
-
|
7
|
+
- Change `IO#gets` to use `String#split` to cut into lines, much faster (see
|
8
|
+
examples/performance/line_splitting.rb)
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
ensure
|
22
|
-
return unless Fiber.current.graceful_shutdown?
|
10
|
+
- More tight loops
|
11
|
+
- `IO#gets_loop`, `Socket#gets_loop`, `OpenSSL::Socket#gets_loop` (medium effort)
|
12
|
+
- `Fiber#receive_loop` (very little effort, should be implemented in C)
|
23
13
|
|
24
|
-
shutdown_gracefully
|
25
|
-
end
|
26
|
-
```
|
27
14
|
|
28
|
-
-
|
29
|
-
fibers, *unless* it was stopped with a `Polyphony::GracefulShutdown` (which it
|
30
|
-
can check with `@graceful_shutdown`).
|
15
|
+
- Add `Backend#splice`, `Backend#splice_loop` for implementing stuff like proxying:
|
31
16
|
|
17
|
+
```ruby
|
18
|
+
def two_way_proxy(socket1, socket2)
|
19
|
+
backend = Thread.current.backend
|
20
|
+
f1 = spin { backend.splice_loop(socket1, socket2) }
|
21
|
+
f2 = spin { backend.splice_loop(socket2, socket1) }
|
22
|
+
Fiber.await(f1, f2)
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
- Graceful shutdown again:
|
27
|
+
- What happens to children when doing a graceful shutdown?
|
28
|
+
- What are the implications of passing graceful shutdown flag to children?
|
29
|
+
- What about errors while doing a graceful shutdown?
|
30
|
+
- What about graceful restarts?
|
31
|
+
- Some interesting discussions:
|
32
|
+
- https://trio.discourse.group/search?q=graceful%20shutdown
|
33
|
+
- https://github.com/python-trio/trio/issues/147
|
34
|
+
- https://github.com/python-trio/trio/issues/143
|
35
|
+
- https://trio.discourse.group/t/graceful-shutdown/93/2
|
36
|
+
- https://250bpm.com/blog:146/
|
37
|
+
- https://www.rodrigoaraujo.me/posts/golang-pattern-graceful-shutdown-of-concurrent-events/
|
38
|
+
- https://github.com/tj/go-gracefully
|
39
|
+
- `Fiber#finalize_children` should pass graceful shutdown flag to children
|
40
|
+
- A good use case is an HTTP server that on graceful shutdown:
|
41
|
+
- stops listening
|
42
|
+
- waits for all ongoing requests to finish, optionally with a timeout
|
32
43
|
|
33
44
|
## Roadmap for Polyphony 1.0
|
34
45
|
|
35
|
-
-
|
46
|
+
- check integration with rb-inotify
|
47
|
+
|
48
|
+
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
49
|
+
inconsistent behaviour (see supervisor example).
|
50
|
+
|
36
51
|
- Add test that mimics the original design for Monocrono:
|
37
52
|
- 256 fibers each waiting for a message
|
38
53
|
- When message received do some blocking work using a `ThreadPool`
|
39
54
|
- Send messages, collect responses, check for correctness
|
40
|
-
- Improve `#supervise`. It does not work as advertised, and seems to exhibit an
|
41
|
-
inconsistent behaviour (see supervisor example).
|
42
55
|
|
43
56
|
- io_uring
|
44
57
|
- 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,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
unix_path = '/tmp/polyphony-unix-socket'
|
8
|
+
|
9
|
+
FileUtils.rm unix_path rescue nil
|
10
|
+
server = UNIXServer.new(unix_path)
|
11
|
+
spin do
|
12
|
+
server.accept_loop do |socket|
|
13
|
+
p [:accept, socket]
|
14
|
+
spin do
|
15
|
+
while (line = socket.gets)
|
16
|
+
socket.puts line
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
snooze
|
23
|
+
client = UNIXSocket.new('/tmp/polyphony-unix-socket')
|
24
|
+
p [:connected, client]
|
25
|
+
client.puts 'hello!'
|
26
|
+
p client.gets
|
@@ -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
|
@@ -70,9 +70,9 @@ inline VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
|
|
70
70
|
|
71
71
|
inline VALUE backend_await(Backend_t *backend) {
|
72
72
|
VALUE ret;
|
73
|
-
backend->
|
73
|
+
backend->pending_count++;
|
74
74
|
ret = Thread_switch_fiber(rb_thread_current());
|
75
|
-
backend->
|
75
|
+
backend->pending_count--;
|
76
76
|
RB_GC_GUARD(ret);
|
77
77
|
return ret;
|
78
78
|
}
|
@@ -27,15 +27,17 @@ static int pidfd_open(pid_t pid, unsigned int flags) {
|
|
27
27
|
return syscall(__NR_pidfd_open, pid, flags);
|
28
28
|
}
|
29
29
|
|
30
|
-
VALUE cTCPSocket;
|
31
30
|
VALUE SYM_io_uring;
|
32
31
|
|
33
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
|
34
39
|
struct io_uring ring;
|
35
40
|
op_context_store_t store;
|
36
|
-
int waiting_for_cqe;
|
37
|
-
unsigned int ref_count;
|
38
|
-
unsigned int run_no_wait_count;
|
39
41
|
unsigned int pending_sqes;
|
40
42
|
unsigned int prepared_limit;
|
41
43
|
int event_fd;
|
@@ -66,11 +68,11 @@ static VALUE Backend_initialize(VALUE self) {
|
|
66
68
|
Backend_t *backend;
|
67
69
|
GetBackend(self, backend);
|
68
70
|
|
69
|
-
backend->
|
70
|
-
backend->
|
71
|
-
backend->
|
71
|
+
backend->currently_polling = 0;
|
72
|
+
backend->pending_count = 0;
|
73
|
+
backend->poll_no_wait_count = 0;
|
72
74
|
backend->pending_sqes = 0;
|
73
|
-
backend->prepared_limit =
|
75
|
+
backend->prepared_limit = 256;
|
74
76
|
|
75
77
|
context_store_initialize(&backend->store);
|
76
78
|
io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
@@ -96,46 +98,19 @@ VALUE Backend_post_fork(VALUE self) {
|
|
96
98
|
io_uring_queue_exit(&backend->ring);
|
97
99
|
io_uring_queue_init(backend->prepared_limit, &backend->ring, 0);
|
98
100
|
context_store_free(&backend->store);
|
99
|
-
backend->
|
100
|
-
backend->
|
101
|
-
backend->
|
101
|
+
backend->currently_polling = 0;
|
102
|
+
backend->pending_count = 0;
|
103
|
+
backend->poll_no_wait_count = 0;
|
102
104
|
backend->pending_sqes = 0;
|
103
105
|
|
104
106
|
return self;
|
105
107
|
}
|
106
108
|
|
107
|
-
|
108
|
-
Backend_t *backend;
|
109
|
-
GetBackend(self, backend);
|
110
|
-
|
111
|
-
backend->ref_count++;
|
112
|
-
return self;
|
113
|
-
}
|
114
|
-
|
115
|
-
VALUE Backend_unref(VALUE self) {
|
109
|
+
unsigned int Backend_pending_count(VALUE self) {
|
116
110
|
Backend_t *backend;
|
117
111
|
GetBackend(self, backend);
|
118
112
|
|
119
|
-
backend->
|
120
|
-
return self;
|
121
|
-
}
|
122
|
-
|
123
|
-
int Backend_ref_count(VALUE self) {
|
124
|
-
Backend_t *backend;
|
125
|
-
GetBackend(self, backend);
|
126
|
-
|
127
|
-
return backend->ref_count;
|
128
|
-
}
|
129
|
-
|
130
|
-
void Backend_reset_ref_count(VALUE self) {
|
131
|
-
Backend_t *backend;
|
132
|
-
GetBackend(self, backend);
|
133
|
-
|
134
|
-
backend->ref_count = 0;
|
135
|
-
}
|
136
|
-
|
137
|
-
VALUE Backend_pending_count(VALUE self) {
|
138
|
-
return INT2NUM(0);
|
113
|
+
return backend->pending_count;
|
139
114
|
}
|
140
115
|
|
141
116
|
typedef struct poll_context {
|
@@ -159,7 +134,7 @@ static inline bool cq_ring_needs_flush(struct io_uring *ring) {
|
|
159
134
|
|
160
135
|
void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *backend) {
|
161
136
|
op_context_t *ctx = io_uring_cqe_get_data(cqe);
|
162
|
-
if (ctx
|
137
|
+
if (!ctx) return;
|
163
138
|
|
164
139
|
ctx->result = cqe->res;
|
165
140
|
|
@@ -212,9 +187,9 @@ void io_uring_backend_poll(Backend_t *backend) {
|
|
212
187
|
io_uring_submit(&backend->ring);
|
213
188
|
}
|
214
189
|
|
215
|
-
backend->
|
190
|
+
backend->currently_polling = 1;
|
216
191
|
rb_thread_call_without_gvl(io_uring_backend_poll_without_gvl, (void *)&poll_ctx, RUBY_UBF_IO, 0);
|
217
|
-
backend->
|
192
|
+
backend->currently_polling = 0;
|
218
193
|
if (poll_ctx.result < 0) return;
|
219
194
|
|
220
195
|
io_uring_backend_handle_completion(poll_ctx.cqe, backend);
|
@@ -227,14 +202,14 @@ VALUE Backend_poll(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue
|
|
227
202
|
GetBackend(self, backend);
|
228
203
|
|
229
204
|
if (is_nowait) {
|
230
|
-
backend->
|
231
|
-
if (backend->
|
205
|
+
backend->poll_no_wait_count++;
|
206
|
+
if (backend->poll_no_wait_count < 10) return self;
|
232
207
|
|
233
208
|
long runnable_count = Runqueue_len(runqueue);
|
234
|
-
if (backend->
|
209
|
+
if (backend->poll_no_wait_count < runnable_count) return self;
|
235
210
|
}
|
236
211
|
|
237
|
-
backend->
|
212
|
+
backend->poll_no_wait_count = 0;
|
238
213
|
|
239
214
|
if (is_nowait && backend->pending_sqes) {
|
240
215
|
backend->pending_sqes = 0;
|
@@ -253,7 +228,7 @@ VALUE Backend_wakeup(VALUE self) {
|
|
253
228
|
Backend_t *backend;
|
254
229
|
GetBackend(self, backend);
|
255
230
|
|
256
|
-
if (backend->
|
231
|
+
if (backend->currently_polling) {
|
257
232
|
// Since we're currently blocking while waiting for a completion, we add a
|
258
233
|
// NOP which would cause the io_uring_enter syscall to return
|
259
234
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
@@ -285,12 +260,12 @@ int io_uring_backend_defer_submit_and_await(
|
|
285
260
|
VALUE switchpoint_result = Qnil;
|
286
261
|
|
287
262
|
io_uring_sqe_set_data(sqe, ctx);
|
288
|
-
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
263
|
+
// io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
289
264
|
io_uring_backend_defer_submit(backend);
|
290
265
|
|
291
|
-
backend->
|
266
|
+
backend->pending_count++;
|
292
267
|
switchpoint_result = backend_await(backend);
|
293
|
-
backend->
|
268
|
+
backend->pending_count--;
|
294
269
|
|
295
270
|
if (!ctx->completed) {
|
296
271
|
ctx->result = -ECANCELED;
|
@@ -352,7 +327,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
352
327
|
|
353
328
|
if (result < 0)
|
354
329
|
rb_syserr_fail(-result, strerror(-result));
|
355
|
-
else if (result
|
330
|
+
else if (!result)
|
356
331
|
break; // EOF
|
357
332
|
else {
|
358
333
|
total += result;
|
@@ -374,7 +349,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
374
349
|
io_set_read_length(str, total, shrinkable);
|
375
350
|
io_enc_str(str, fptr);
|
376
351
|
|
377
|
-
if (total
|
352
|
+
if (!total) return Qnil;
|
378
353
|
|
379
354
|
return str;
|
380
355
|
}
|
@@ -411,7 +386,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
411
386
|
|
412
387
|
if (result < 0)
|
413
388
|
rb_syserr_fail(-result, strerror(-result));
|
414
|
-
else if (result
|
389
|
+
else if (!result)
|
415
390
|
break; // EOF
|
416
391
|
else {
|
417
392
|
total = result;
|
@@ -582,7 +557,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
582
557
|
io_set_read_length(str, total, shrinkable);
|
583
558
|
io_enc_str(str, fptr);
|
584
559
|
|
585
|
-
if (total
|
560
|
+
if (!total) return Qnil;
|
586
561
|
|
587
562
|
return str;
|
588
563
|
}
|
@@ -619,7 +594,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io) {
|
|
619
594
|
|
620
595
|
if (result < 0)
|
621
596
|
rb_syserr_fail(-result, strerror(-result));
|
622
|
-
else if (result
|
597
|
+
else if (!result)
|
623
598
|
break; // EOF
|
624
599
|
else {
|
625
600
|
total = result;
|
@@ -669,15 +644,15 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str) {
|
|
669
644
|
return INT2NUM(len);
|
670
645
|
}
|
671
646
|
|
672
|
-
VALUE io_uring_backend_accept(Backend_t *backend, VALUE
|
647
|
+
VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE socket_class, int loop) {
|
673
648
|
rb_io_t *fptr;
|
674
649
|
struct sockaddr addr;
|
675
650
|
socklen_t len = (socklen_t)sizeof addr;
|
676
|
-
VALUE underlying_sock = rb_ivar_get(sock, ID_ivar_io);
|
677
651
|
VALUE socket = Qnil;
|
678
|
-
|
652
|
+
VALUE underlying_sock = rb_ivar_get(server_socket, ID_ivar_io);
|
653
|
+
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
679
654
|
|
680
|
-
GetOpenFile(
|
655
|
+
GetOpenFile(server_socket, fptr);
|
681
656
|
while (1) {
|
682
657
|
VALUE resume_value = Qnil;
|
683
658
|
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_ACCEPT);
|
@@ -695,7 +670,7 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE sock, int loop) {
|
|
695
670
|
else {
|
696
671
|
rb_io_t *fp;
|
697
672
|
|
698
|
-
socket = rb_obj_alloc(
|
673
|
+
socket = rb_obj_alloc(socket_class);
|
699
674
|
MakeOpenFile(socket, fp);
|
700
675
|
rb_update_max_fd(fd);
|
701
676
|
fp->fd = fd;
|
@@ -718,16 +693,16 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE sock, 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,19 +920,12 @@ VALUE Backend_kind(VALUE self) {
|
|
945
920
|
}
|
946
921
|
|
947
922
|
void Init_Backend() {
|
948
|
-
rb_require("socket");
|
949
|
-
cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
950
|
-
|
951
923
|
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cData);
|
952
924
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
953
925
|
|
954
926
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
955
927
|
rb_define_method(cBackend, "finalize", Backend_finalize, 0);
|
956
928
|
rb_define_method(cBackend, "post_fork", Backend_post_fork, 0);
|
957
|
-
rb_define_method(cBackend, "pending_count", Backend_pending_count, 0);
|
958
|
-
|
959
|
-
rb_define_method(cBackend, "ref", Backend_ref, 0);
|
960
|
-
rb_define_method(cBackend, "unref", Backend_unref, 0);
|
961
929
|
|
962
930
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
963
931
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
@@ -968,8 +936,8 @@ void Init_Backend() {
|
|
968
936
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
969
937
|
rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 1);
|
970
938
|
rb_define_method(cBackend, "send", Backend_send, 2);
|
971
|
-
rb_define_method(cBackend, "accept", Backend_accept,
|
972
|
-
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);
|
973
941
|
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
974
942
|
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
975
943
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
@@ -981,15 +949,6 @@ void Init_Backend() {
|
|
981
949
|
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
982
950
|
|
983
951
|
SYM_io_uring = ID2SYM(rb_intern("io_uring"));
|
984
|
-
|
985
|
-
__BACKEND__.pending_count = Backend_pending_count;
|
986
|
-
__BACKEND__.poll = Backend_poll;
|
987
|
-
__BACKEND__.ref = Backend_ref;
|
988
|
-
__BACKEND__.ref_count = Backend_ref_count;
|
989
|
-
__BACKEND__.reset_ref_count = Backend_reset_ref_count;
|
990
|
-
__BACKEND__.unref = Backend_unref;
|
991
|
-
__BACKEND__.wait_event = Backend_wait_event;
|
992
|
-
__BACKEND__.wakeup = Backend_wakeup;
|
993
952
|
}
|
994
953
|
|
995
954
|
#endif // POLYPHONY_BACKEND_LIBURING
|