polyphony 0.47.3 → 0.49.0
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 +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
|