polyphony 0.50.0 → 0.53.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/workflows/test.yml +1 -1
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +7 -68
- data/TODO.md +37 -6
- data/examples/core/forking.rb +2 -2
- data/examples/io/echo_server.rb +1 -0
- data/examples/io/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +57 -7
- data/ext/polyphony/backend_io_uring.c +232 -49
- data/ext/polyphony/backend_io_uring_context.c +1 -0
- data/ext/polyphony/backend_io_uring_context.h +1 -0
- data/ext/polyphony/backend_libev.c +355 -34
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +9 -2
- data/ext/polyphony/polyphony.c +102 -0
- data/ext/polyphony/polyphony.h +32 -2
- data/ext/polyphony/polyphony_ext.c +3 -0
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +1 -1
- data/ext/polyphony/socket_extensions.c +33 -0
- data/ext/polyphony/thread.c +8 -2
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/adapters/mysql2.rb +1 -1
- data/lib/polyphony/adapters/postgres.rb +5 -5
- data/lib/polyphony/adapters/process.rb +4 -4
- data/lib/polyphony/core/global_api.rb +5 -5
- data/lib/polyphony/core/sync.rb +1 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/extensions/core.rb +1 -1
- data/lib/polyphony/extensions/io.rb +21 -22
- data/lib/polyphony/extensions/openssl.rb +6 -6
- data/lib/polyphony/extensions/socket.rb +56 -47
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +6 -5
- data/test/helper.rb +1 -1
- data/test/stress.rb +2 -0
- data/test/test_backend.rb +152 -5
- data/test/test_global_api.rb +2 -2
- data/test/test_io.rb +84 -1
- data/test/test_kernel.rb +1 -1
- data/test/test_signal.rb +1 -1
- data/test/test_socket.rb +61 -0
- data/test/test_thread.rb +4 -0
- data/test/test_timer.rb +1 -1
- metadata +19 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b769b5e71cbfa8679a639d369817abd8e5870efec8ea21feb60bb1e46ee7ca29
|
4
|
+
data.tar.gz: 0b2ded84eb0e120d20dd17c9973e2cab784cdf61c20bd20fcb6a13c2b6e9f58a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6d3a3d2c130c31483ead4d8f13cc90a87149ac6c461871a43144111cdc37e6e2544c130dc447af26e39e9519b48e3abe1a10197dd4512a7292968e4939e676b
|
7
|
+
data.tar.gz: dc1b53918032fc74578ca528abb5a96e423ea8e7a070047f7936720cb6553d9f247cbb625e9d82c7b9b58795a4a3a74aae566231a7a4bb8443f5352c00d10b2a
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
## 0.53.1
|
2
|
+
|
3
|
+
- Remove `splice` methods on libev backend on non-Linux OS (#43)
|
4
|
+
|
5
|
+
## 0.53.0
|
6
|
+
|
7
|
+
- Implement `Backend#splice`, `Backend#splice_to_eof`, along with `IO#splice`, `IO#splice_to_eof`
|
8
|
+
|
9
|
+
## 0.52.0
|
10
|
+
|
11
|
+
- Polyphony is now compatible with Ruby 3.0
|
12
|
+
- Add `Backend#sendv` method for sending multiple strings
|
13
|
+
- Accept flags argument in `Backend#send` (#48)
|
14
|
+
- Fix io_uring backend on Ruby 3.0 (#47)
|
15
|
+
- Implement C-based public backend API: `Polyphony.backend_XXXX` methods
|
16
|
+
- libev backend: Use` pidfd_open` for Linux 5.3+, otherwise use a libev child watcher
|
17
|
+
- Use `:call` as default method in `#feed_loop`
|
18
|
+
|
19
|
+
## 0.51.0
|
20
|
+
|
21
|
+
- Implement `IO#feed_loop`, `Socket#feed_loop`
|
22
|
+
- Fix error handling in `Process.kill_and_await`
|
23
|
+
|
24
|
+
## 0.50.1
|
25
|
+
|
26
|
+
- Set `IOSQE_ASYNC` flag in io_uring backend
|
27
|
+
- Fix error handling in `Backend#waitpid`
|
28
|
+
- Reimplement libev backend's `#waitpid` by using pidfd_open (in similar manner
|
29
|
+
to the io_uring backend)
|
30
|
+
|
1
31
|
## 0.50.0
|
2
32
|
|
3
33
|
- Use `Process::CLOCK_MONOTONIC` in Timer
|
data/Gemfile.lock
CHANGED
@@ -1,101 +1,50 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
polyphony (0.
|
4
|
+
polyphony (0.53.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
addressable (2.7.0)
|
10
|
-
public_suffix (>= 2.0.2, < 5.0)
|
11
9
|
ansi (1.5.0)
|
12
10
|
ast (2.4.0)
|
13
11
|
builder (3.2.4)
|
14
12
|
coderay (1.1.3)
|
15
|
-
colorator (1.1.0)
|
16
|
-
concurrent-ruby (1.1.6)
|
17
13
|
docile (1.3.2)
|
18
|
-
em-websocket (0.5.1)
|
19
|
-
eventmachine (>= 0.12.9)
|
20
|
-
http_parser.rb (~> 0.6.0)
|
21
|
-
eventmachine (1.2.7)
|
22
|
-
ffi (1.12.1)
|
23
|
-
forwardable-extended (2.6.0)
|
24
14
|
hiredis (0.6.3)
|
25
15
|
http_parser.rb (0.6.0)
|
26
16
|
httparty (0.17.1)
|
27
17
|
mime-types (~> 3.0)
|
28
18
|
multi_xml (>= 0.5.2)
|
29
|
-
i18n (0.9.5)
|
30
|
-
concurrent-ruby (~> 1.0)
|
31
|
-
jekyll (3.8.6)
|
32
|
-
addressable (~> 2.4)
|
33
|
-
colorator (~> 1.0)
|
34
|
-
em-websocket (~> 0.5)
|
35
|
-
i18n (~> 0.7)
|
36
|
-
jekyll-sass-converter (~> 1.0)
|
37
|
-
jekyll-watch (~> 2.0)
|
38
|
-
kramdown (~> 1.14)
|
39
|
-
liquid (~> 4.0)
|
40
|
-
mercenary (~> 0.3.3)
|
41
|
-
pathutil (~> 0.9)
|
42
|
-
rouge (>= 1.7, < 4)
|
43
|
-
safe_yaml (~> 1.0)
|
44
|
-
jekyll-remote-theme (0.4.1)
|
45
|
-
addressable (~> 2.0)
|
46
|
-
jekyll (>= 3.5, < 5.0)
|
47
|
-
rubyzip (>= 1.3.0)
|
48
|
-
jekyll-sass-converter (1.5.2)
|
49
|
-
sass (~> 3.4)
|
50
|
-
jekyll-seo-tag (2.6.1)
|
51
|
-
jekyll (>= 3.3, < 5.0)
|
52
|
-
jekyll-watch (2.2.1)
|
53
|
-
listen (~> 3.0)
|
54
19
|
json (2.3.0)
|
55
|
-
just-the-docs (0.3.0)
|
56
|
-
jekyll (>= 3.8.5)
|
57
|
-
jekyll-seo-tag (~> 2.0)
|
58
|
-
rake (>= 12.3.1, < 13.1.0)
|
59
|
-
kramdown (1.17.0)
|
60
|
-
liquid (4.0.3)
|
61
|
-
listen (3.2.1)
|
62
|
-
rb-fsevent (~> 0.10, >= 0.10.3)
|
63
|
-
rb-inotify (~> 0.9, >= 0.9.10)
|
64
|
-
mercenary (0.3.6)
|
65
20
|
method_source (1.0.0)
|
66
21
|
mime-types (3.3.1)
|
67
22
|
mime-types-data (~> 3.2015)
|
68
23
|
mime-types-data (3.2020.0512)
|
69
|
-
minitest (5.
|
24
|
+
minitest (5.14.4)
|
70
25
|
minitest-reporters (1.4.2)
|
71
26
|
ansi
|
72
27
|
builder
|
73
28
|
minitest (>= 5.0)
|
74
29
|
ruby-progressbar
|
30
|
+
msgpack (1.4.2)
|
75
31
|
multi_xml (0.6.0)
|
76
32
|
mysql2 (0.5.3)
|
77
33
|
parallel (1.19.1)
|
78
34
|
parser (2.7.0.2)
|
79
35
|
ast (~> 2.4.0)
|
80
|
-
pathutil (0.16.2)
|
81
|
-
forwardable-extended (~> 2.6)
|
82
36
|
pg (1.1.4)
|
83
37
|
pry (0.13.1)
|
84
38
|
coderay (~> 1.1)
|
85
39
|
method_source (~> 1.0)
|
86
|
-
public_suffix (4.0.3)
|
87
40
|
rack (2.2.3)
|
88
41
|
rainbow (3.0.0)
|
89
|
-
rake (
|
42
|
+
rake (13.0.3)
|
90
43
|
rake-compiler (1.1.1)
|
91
44
|
rake
|
92
|
-
rb-fsevent (0.10.3)
|
93
|
-
rb-inotify (0.10.1)
|
94
|
-
ffi (~> 1.0)
|
95
45
|
redis (4.1.0)
|
96
46
|
regexp_parser (1.7.1)
|
97
47
|
rexml (3.2.4)
|
98
|
-
rouge (3.15.0)
|
99
48
|
rubocop (0.85.1)
|
100
49
|
parallel (~> 1.10)
|
101
50
|
parser (>= 2.7.0.1)
|
@@ -108,13 +57,6 @@ GEM
|
|
108
57
|
rubocop-ast (0.0.3)
|
109
58
|
parser (>= 2.7.0.1)
|
110
59
|
ruby-progressbar (1.10.1)
|
111
|
-
rubyzip (2.0.0)
|
112
|
-
safe_yaml (1.0.5)
|
113
|
-
sass (3.7.4)
|
114
|
-
sass-listen (~> 4.0.0)
|
115
|
-
sass-listen (4.0.0)
|
116
|
-
rb-fsevent (~> 0.9, >= 0.9.4)
|
117
|
-
rb-inotify (~> 0.9, >= 0.9.7)
|
118
60
|
sequel (5.34.0)
|
119
61
|
simplecov (0.17.1)
|
120
62
|
docile (~> 1.1)
|
@@ -130,12 +72,9 @@ DEPENDENCIES
|
|
130
72
|
hiredis (= 0.6.3)
|
131
73
|
http_parser.rb (~> 0.6.0)
|
132
74
|
httparty (= 0.17.1)
|
133
|
-
|
134
|
-
jekyll-remote-theme (~> 0.4.1)
|
135
|
-
jekyll-seo-tag (~> 2.6.1)
|
136
|
-
just-the-docs (~> 0.3.0)
|
137
|
-
minitest (= 5.13.0)
|
75
|
+
minitest (= 5.14.4)
|
138
76
|
minitest-reporters (= 1.4.2)
|
77
|
+
msgpack (= 1.4.2)
|
139
78
|
mysql2 (= 0.5.3)
|
140
79
|
pg (= 1.1.4)
|
141
80
|
polyphony!
|
@@ -148,4 +87,4 @@ DEPENDENCIES
|
|
148
87
|
simplecov (= 0.17.1)
|
149
88
|
|
150
89
|
BUNDLED WITH
|
151
|
-
2.
|
90
|
+
2.2.3
|
data/TODO.md
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
- Add support for IPv6:
|
2
|
+
https://www.reddit.com/r/ruby/comments/lyen23/understanding_ipv6_and_why_its_important_to_you/
|
3
|
+
|
4
|
+
- Add support for UDP sockets
|
5
|
+
|
1
6
|
- Check segfault when resetting a `cancel_after` timeout lots of times at very high rate
|
2
7
|
- Check why `throttled_loop` inside of `move_on_after` fails to stop
|
3
8
|
|
4
|
-
- Commented out `io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);` in `io_uring_backend_defer_submit_and_await`:
|
5
|
-
- This flag should be set for I/O ops, not for other stuff
|
6
|
-
|
7
9
|
- Override stock `::SizedQueue` impl with Queue with capacity
|
8
10
|
|
9
11
|
- Add support for `break` and `StopIteration` in all loops (with tests)
|
@@ -16,17 +18,46 @@
|
|
16
18
|
- `Fiber#receive_loop` (very little effort, should be implemented in C)
|
17
19
|
|
18
20
|
|
19
|
-
- Add `Backend#splice`, `Backend#
|
21
|
+
- Add `Backend#splice`, `Backend#splice_to_eof` for implementing stuff like proxying:
|
20
22
|
|
21
23
|
```ruby
|
22
24
|
def two_way_proxy(socket1, socket2)
|
23
25
|
backend = Thread.current.backend
|
24
|
-
f1 = spin { backend.
|
25
|
-
f2 = spin { backend.
|
26
|
+
f1 = spin { backend.splice_to_eof(socket1, socket2) }
|
27
|
+
f2 = spin { backend.splice_to_eof(socket2, socket1) }
|
26
28
|
Fiber.await(f1, f2)
|
27
29
|
end
|
28
30
|
```
|
29
31
|
|
32
|
+
- Add support for `close` to io_uring backend
|
33
|
+
|
34
|
+
- Add support for submission of multiple requests to io_uring backend:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
Thread.current.backend.submit(
|
38
|
+
[:send, sock, chunk_header(len)],
|
39
|
+
[:splice, file, sock, len]
|
40
|
+
)
|
41
|
+
```
|
42
|
+
|
43
|
+
Full example (for writing chunks from a file to an HTTP response):
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
def serve_io(io)
|
47
|
+
i, o = IO.pipe
|
48
|
+
backend = Thread.current.backend
|
49
|
+
while true
|
50
|
+
len = o.splice(io, 8192)
|
51
|
+
break if len == 0
|
52
|
+
|
53
|
+
backend.submit(
|
54
|
+
[:write, sock, chunk_header(len)],
|
55
|
+
[:splice, i, sock, len]
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
30
61
|
- Graceful shutdown again:
|
31
62
|
- What happens to children when doing a graceful shutdown?
|
32
63
|
- What are the implications of passing graceful shutdown flag to children?
|
data/examples/core/forking.rb
CHANGED
@@ -5,7 +5,7 @@ require 'polyphony'
|
|
5
5
|
|
6
6
|
puts "parent pid: #{Process.pid}"
|
7
7
|
|
8
|
-
pid =
|
8
|
+
pid = fork do
|
9
9
|
puts "child pid: #{Process.pid}"
|
10
10
|
|
11
11
|
spin do
|
@@ -20,5 +20,5 @@ end
|
|
20
20
|
puts "got child pid #{pid}"
|
21
21
|
|
22
22
|
puts 'parent waiting for child'
|
23
|
-
|
23
|
+
Polyphony.backend_waitpid(pid)
|
24
24
|
puts 'parent done waiting'
|
data/examples/io/echo_server.rb
CHANGED
data/examples/io/tcp_proxy.rb
CHANGED
@@ -15,7 +15,7 @@ f1 = spin {
|
|
15
15
|
client1 = server1.accept
|
16
16
|
loop do
|
17
17
|
if client2
|
18
|
-
Thread.current.backend.
|
18
|
+
Thread.current.backend.splice_to_eof(client1, client2)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
}
|
@@ -24,7 +24,7 @@ f2 = spin {
|
|
24
24
|
client2 = server2.accept
|
25
25
|
loop do
|
26
26
|
if client1
|
27
|
-
Thread.current.backend.
|
27
|
+
Thread.current.backend.splice_to_eof(client2, client1)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
}
|
@@ -3,6 +3,17 @@
|
|
3
3
|
#include "ruby.h"
|
4
4
|
#include "ruby/io.h"
|
5
5
|
|
6
|
+
|
7
|
+
#ifdef POLYPHONY_USE_PIDFD_OPEN
|
8
|
+
#ifndef __NR_pidfd_open
|
9
|
+
#define __NR_pidfd_open 434 /* System call # on most architectures */
|
10
|
+
#endif
|
11
|
+
|
12
|
+
static int pidfd_open(pid_t pid, unsigned int flags) {
|
13
|
+
return syscall(__NR_pidfd_open, pid, flags);
|
14
|
+
}
|
15
|
+
#endif
|
16
|
+
|
6
17
|
//////////////////////////////////////////////////////////////////////
|
7
18
|
//////////////////////////////////////////////////////////////////////
|
8
19
|
// the following is copied verbatim from the Ruby source code (io.c)
|
@@ -15,11 +26,11 @@ struct io_internal_read_struct {
|
|
15
26
|
|
16
27
|
#define StringValue(v) rb_string_value(&(v))
|
17
28
|
|
18
|
-
|
29
|
+
int io_setstrbuf(VALUE *str, long len) {
|
19
30
|
#ifdef _WIN32
|
20
31
|
len = (len + 1) & ~1L; /* round up for wide char */
|
21
32
|
#endif
|
22
|
-
if (
|
33
|
+
if (*str == Qnil) {
|
23
34
|
*str = rb_str_new(0, len);
|
24
35
|
return 1;
|
25
36
|
}
|
@@ -44,7 +55,7 @@ inline void io_shrink_read_string(VALUE str, long n) {
|
|
44
55
|
}
|
45
56
|
}
|
46
57
|
|
47
|
-
|
58
|
+
void io_set_read_length(VALUE str, long n, int shrinkable) {
|
48
59
|
if (RSTRING_LEN(str) != n) {
|
49
60
|
rb_str_modify(str);
|
50
61
|
rb_str_set_len(str, n);
|
@@ -59,7 +70,7 @@ inline rb_encoding* io_read_encoding(rb_io_t *fptr) {
|
|
59
70
|
return rb_default_external_encoding();
|
60
71
|
}
|
61
72
|
|
62
|
-
|
73
|
+
VALUE io_enc_str(VALUE str, rb_io_t *fptr) {
|
63
74
|
OBJ_TAINT(str);
|
64
75
|
rb_enc_associate(str, io_read_encoding(fptr));
|
65
76
|
return str;
|
@@ -99,6 +110,13 @@ inline VALUE backend_snooze() {
|
|
99
110
|
READ_LOOP_PREPARE_STR(); \
|
100
111
|
}
|
101
112
|
|
113
|
+
#define READ_LOOP_PASS_STR_TO_RECEIVER(receiver, method_id) { \
|
114
|
+
io_set_read_length(str, total, shrinkable); \
|
115
|
+
io_enc_str(str, fptr); \
|
116
|
+
rb_funcall_passing_block(receiver, method_id, 1, &str); \
|
117
|
+
READ_LOOP_PREPARE_STR(); \
|
118
|
+
}
|
119
|
+
|
102
120
|
inline void rectify_io_file_pos(rb_io_t *fptr) {
|
103
121
|
// Apparently after reopening a closed file, the file position is not reset,
|
104
122
|
// which causes the read to fail. Fortunately we can use fptr->rbuf.len to
|
@@ -120,10 +138,42 @@ inline double current_time() {
|
|
120
138
|
}
|
121
139
|
|
122
140
|
inline VALUE backend_timeout_exception(VALUE exception) {
|
123
|
-
if (
|
141
|
+
if (rb_obj_is_kind_of(exception, rb_cArray) == Qtrue)
|
124
142
|
return rb_funcall(rb_ary_entry(exception, 0), ID_new, 1, rb_ary_entry(exception, 1));
|
125
|
-
else if (
|
143
|
+
else if (rb_obj_is_kind_of(exception, rb_cClass) == Qtrue)
|
126
144
|
return rb_funcall(exception, ID_new, 0);
|
127
145
|
else
|
128
146
|
return rb_funcall(rb_eRuntimeError, ID_new, 1, exception);
|
129
|
-
}
|
147
|
+
}
|
148
|
+
|
149
|
+
VALUE Backend_timeout_safe(VALUE arg) {
|
150
|
+
return rb_yield(arg);
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE Backend_timeout_rescue(VALUE arg, VALUE exception) {
|
154
|
+
return exception;
|
155
|
+
}
|
156
|
+
|
157
|
+
VALUE Backend_timeout_ensure_safe(VALUE arg) {
|
158
|
+
return rb_rescue2(Backend_timeout_safe, Qnil, Backend_timeout_rescue, Qnil, rb_eException, (VALUE)0);
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE empty_string = Qnil;
|
162
|
+
|
163
|
+
VALUE Backend_sendv(VALUE self, VALUE io, VALUE ary, VALUE flags) {
|
164
|
+
switch (RARRAY_LEN(ary)) {
|
165
|
+
case 0:
|
166
|
+
return Qnil;
|
167
|
+
case 1:
|
168
|
+
return Backend_send(self, io, RARRAY_AREF(ary, 0), flags);
|
169
|
+
default:
|
170
|
+
if (empty_string == Qnil) {
|
171
|
+
empty_string = rb_str_new_literal("");
|
172
|
+
rb_global_variable(&empty_string);
|
173
|
+
}
|
174
|
+
VALUE joined = rb_ary_join(ary, empty_string);
|
175
|
+
VALUE result = Backend_send(self, io, joined, flags);
|
176
|
+
RB_GC_GUARD(joined);
|
177
|
+
return result;
|
178
|
+
}
|
179
|
+
}
|
@@ -16,18 +16,36 @@
|
|
16
16
|
|
17
17
|
#include "polyphony.h"
|
18
18
|
#include "../liburing/liburing.h"
|
19
|
-
#include "ruby/thread.h"
|
20
19
|
#include "backend_io_uring_context.h"
|
20
|
+
#include "ruby/thread.h"
|
21
|
+
#include "ruby/io.h"
|
21
22
|
|
22
|
-
|
23
|
-
#define __NR_pidfd_open 434 /* System call # on most architectures */
|
24
|
-
#endif
|
23
|
+
VALUE SYM_io_uring;
|
25
24
|
|
26
|
-
|
27
|
-
|
25
|
+
#ifdef POLYPHONY_UNSET_NONBLOCK
|
26
|
+
ID ID_ivar_is_nonblocking;
|
27
|
+
|
28
|
+
// One of the changes introduced in Ruby 3.0 as part of the work on the
|
29
|
+
// FiberScheduler interface is that all created sockets are marked as
|
30
|
+
// non-blocking. This prevents the io_uring backend from working correctly,
|
31
|
+
// since it will return an EAGAIN error just like a normal syscall. So here
|
32
|
+
// instead of setting O_NONBLOCK (which is required for the libev backend), we
|
33
|
+
// unset it.
|
34
|
+
inline void io_unset_nonblock(rb_io_t *fptr, VALUE io) {
|
35
|
+
VALUE is_nonblocking = rb_ivar_get(io, ID_ivar_is_nonblocking);
|
36
|
+
if (is_nonblocking == Qfalse) return;
|
37
|
+
|
38
|
+
rb_ivar_set(io, ID_ivar_is_nonblocking, Qfalse);
|
39
|
+
|
40
|
+
int oflags = fcntl(fptr->fd, F_GETFL);
|
41
|
+
if ((oflags == -1) && (oflags & O_NONBLOCK)) return;
|
42
|
+
oflags &= !O_NONBLOCK;
|
43
|
+
fcntl(fptr->fd, F_SETFL, oflags);
|
28
44
|
}
|
29
|
-
|
30
|
-
|
45
|
+
#else
|
46
|
+
// NOP
|
47
|
+
#define io_unset_nonblock(fptr, io)
|
48
|
+
#endif
|
31
49
|
|
32
50
|
typedef struct Backend_t {
|
33
51
|
// common fields
|
@@ -132,7 +150,7 @@ static inline bool cq_ring_needs_flush(struct io_uring *ring) {
|
|
132
150
|
return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW;
|
133
151
|
}
|
134
152
|
|
135
|
-
void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *backend) {
|
153
|
+
static inline void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *backend) {
|
136
154
|
op_context_t *ctx = io_uring_cqe_get_data(cqe);
|
137
155
|
if (!ctx) return;
|
138
156
|
|
@@ -151,7 +169,7 @@ void io_uring_backend_handle_completion(struct io_uring_cqe *cqe, Backend_t *bac
|
|
151
169
|
}
|
152
170
|
|
153
171
|
// adapted from io_uring_peek_batch_cqe in queue.c
|
154
|
-
// this peeks at cqes and
|
172
|
+
// this peeks at cqes and handles each available cqe
|
155
173
|
void io_uring_backend_handle_ready_cqes(Backend_t *backend) {
|
156
174
|
struct io_uring *ring = &backend->ring;
|
157
175
|
bool overflow_checked = false;
|
@@ -260,7 +278,7 @@ int io_uring_backend_defer_submit_and_await(
|
|
260
278
|
VALUE switchpoint_result = Qnil;
|
261
279
|
|
262
280
|
io_uring_sqe_set_data(sqe, ctx);
|
263
|
-
|
281
|
+
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
264
282
|
io_uring_backend_defer_submit(backend);
|
265
283
|
|
266
284
|
switchpoint_result = backend_await(backend);
|
@@ -297,8 +315,8 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
297
315
|
Backend_t *backend;
|
298
316
|
rb_io_t *fptr;
|
299
317
|
long dynamic_len = length == Qnil;
|
300
|
-
long
|
301
|
-
int shrinkable = io_setstrbuf(&str,
|
318
|
+
long buffer_size = dynamic_len ? 4096 : NUM2INT(length);
|
319
|
+
int shrinkable = io_setstrbuf(&str, buffer_size);
|
302
320
|
char *buf = RSTRING_PTR(str);
|
303
321
|
long total = 0;
|
304
322
|
int read_to_eof = RTEST(to_eof);
|
@@ -308,6 +326,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
308
326
|
if (underlying_io != Qnil) io = underlying_io;
|
309
327
|
GetOpenFile(io, fptr);
|
310
328
|
rb_io_check_byte_readable(fptr);
|
329
|
+
io_unset_nonblock(fptr, io);
|
311
330
|
rectify_io_file_pos(fptr);
|
312
331
|
OBJ_TAINT(str);
|
313
332
|
|
@@ -315,7 +334,7 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
315
334
|
VALUE resume_value = Qnil;
|
316
335
|
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_READ);
|
317
336
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
318
|
-
io_uring_prep_read(sqe, fptr->fd, buf,
|
337
|
+
io_uring_prep_read(sqe, fptr->fd, buf, buffer_size - total, -1);
|
319
338
|
|
320
339
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
321
340
|
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
@@ -331,14 +350,15 @@ VALUE Backend_read(VALUE self, VALUE io, VALUE str, VALUE length, VALUE to_eof)
|
|
331
350
|
total += result;
|
332
351
|
if (!read_to_eof) break;
|
333
352
|
|
334
|
-
if (total ==
|
353
|
+
if (total == buffer_size) {
|
335
354
|
if (!dynamic_len) break;
|
336
355
|
|
356
|
+
// resize buffer
|
337
357
|
rb_str_resize(str, total);
|
338
|
-
rb_str_modify_expand(str,
|
358
|
+
rb_str_modify_expand(str, buffer_size);
|
339
359
|
buf = RSTRING_PTR(str) + total;
|
340
360
|
shrinkable = 0;
|
341
|
-
|
361
|
+
buffer_size += buffer_size;
|
342
362
|
}
|
343
363
|
else buf += result;
|
344
364
|
}
|
@@ -368,6 +388,7 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
368
388
|
if (underlying_io != Qnil) io = underlying_io;
|
369
389
|
GetOpenFile(io, fptr);
|
370
390
|
rb_io_check_byte_readable(fptr);
|
391
|
+
io_unset_nonblock(fptr, io);
|
371
392
|
rectify_io_file_pos(fptr);
|
372
393
|
|
373
394
|
while (1) {
|
@@ -397,6 +418,53 @@ VALUE Backend_read_loop(VALUE self, VALUE io) {
|
|
397
418
|
return io;
|
398
419
|
}
|
399
420
|
|
421
|
+
VALUE Backend_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
422
|
+
Backend_t *backend;
|
423
|
+
rb_io_t *fptr;
|
424
|
+
VALUE str;
|
425
|
+
long total;
|
426
|
+
long len = 8192;
|
427
|
+
int shrinkable;
|
428
|
+
char *buf;
|
429
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
430
|
+
ID method_id = SYM2ID(method);
|
431
|
+
|
432
|
+
READ_LOOP_PREPARE_STR();
|
433
|
+
|
434
|
+
GetBackend(self, backend);
|
435
|
+
if (underlying_io != Qnil) io = underlying_io;
|
436
|
+
GetOpenFile(io, fptr);
|
437
|
+
rb_io_check_byte_readable(fptr);
|
438
|
+
io_unset_nonblock(fptr, io);
|
439
|
+
rectify_io_file_pos(fptr);
|
440
|
+
|
441
|
+
while (1) {
|
442
|
+
VALUE resume_value = Qnil;
|
443
|
+
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_READ);
|
444
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
445
|
+
io_uring_prep_read(sqe, fptr->fd, buf, len, -1);
|
446
|
+
|
447
|
+
ssize_t result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
448
|
+
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
449
|
+
RAISE_IF_EXCEPTION(resume_value);
|
450
|
+
if (!ctx->completed) return resume_value;
|
451
|
+
RB_GC_GUARD(resume_value);
|
452
|
+
|
453
|
+
if (result < 0)
|
454
|
+
rb_syserr_fail(-result, strerror(-result));
|
455
|
+
else if (!result)
|
456
|
+
break; // EOF
|
457
|
+
else {
|
458
|
+
total = result;
|
459
|
+
READ_LOOP_PASS_STR_TO_RECEIVER(receiver, method_id);
|
460
|
+
}
|
461
|
+
}
|
462
|
+
|
463
|
+
RB_GC_GUARD(str);
|
464
|
+
|
465
|
+
return io;
|
466
|
+
}
|
467
|
+
|
400
468
|
VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
401
469
|
Backend_t *backend;
|
402
470
|
rb_io_t *fptr;
|
@@ -407,6 +475,7 @@ VALUE Backend_write(VALUE self, VALUE io, VALUE str) {
|
|
407
475
|
GetBackend(self, backend);
|
408
476
|
io = rb_io_get_write_io(io);
|
409
477
|
GetOpenFile(io, fptr);
|
478
|
+
io_unset_nonblock(fptr, io);
|
410
479
|
|
411
480
|
char *buf = StringValuePtr(str);
|
412
481
|
long len = RSTRING_LEN(str);
|
@@ -450,6 +519,7 @@ VALUE Backend_writev(VALUE self, VALUE io, int argc, VALUE *argv) {
|
|
450
519
|
GetBackend(self, backend);
|
451
520
|
io = rb_io_get_write_io(io);
|
452
521
|
GetOpenFile(io, fptr);
|
522
|
+
io_unset_nonblock(fptr, io);
|
453
523
|
|
454
524
|
iov = malloc(iov_count * sizeof(struct iovec));
|
455
525
|
for (int i = 0; i < argc; i++) {
|
@@ -529,6 +599,7 @@ VALUE Backend_recv(VALUE self, VALUE io, VALUE str, VALUE length) {
|
|
529
599
|
if (underlying_io != Qnil) io = underlying_io;
|
530
600
|
GetOpenFile(io, fptr);
|
531
601
|
rb_io_check_byte_readable(fptr);
|
602
|
+
io_unset_nonblock(fptr, io);
|
532
603
|
rectify_io_file_pos(fptr);
|
533
604
|
OBJ_TAINT(str);
|
534
605
|
|
@@ -576,6 +647,7 @@ VALUE Backend_recv_loop(VALUE self, VALUE io) {
|
|
576
647
|
if (underlying_io != Qnil) io = underlying_io;
|
577
648
|
GetOpenFile(io, fptr);
|
578
649
|
rb_io_check_byte_readable(fptr);
|
650
|
+
io_unset_nonblock(fptr, io);
|
579
651
|
rectify_io_file_pos(fptr);
|
580
652
|
|
581
653
|
while (1) {
|
@@ -604,7 +676,53 @@ VALUE Backend_recv_loop(VALUE self, VALUE io) {
|
|
604
676
|
return io;
|
605
677
|
}
|
606
678
|
|
607
|
-
VALUE
|
679
|
+
VALUE Backend_recv_feed_loop(VALUE self, VALUE io, VALUE receiver, VALUE method) {
|
680
|
+
Backend_t *backend;
|
681
|
+
rb_io_t *fptr;
|
682
|
+
VALUE str;
|
683
|
+
long total;
|
684
|
+
long len = 8192;
|
685
|
+
int shrinkable;
|
686
|
+
char *buf;
|
687
|
+
VALUE underlying_io = rb_ivar_get(io, ID_ivar_io);
|
688
|
+
ID method_id = SYM2ID(method);
|
689
|
+
|
690
|
+
READ_LOOP_PREPARE_STR();
|
691
|
+
|
692
|
+
GetBackend(self, backend);
|
693
|
+
if (underlying_io != Qnil) io = underlying_io;
|
694
|
+
GetOpenFile(io, fptr);
|
695
|
+
rb_io_check_byte_readable(fptr);
|
696
|
+
io_unset_nonblock(fptr, io);
|
697
|
+
rectify_io_file_pos(fptr);
|
698
|
+
|
699
|
+
while (1) {
|
700
|
+
VALUE resume_value = Qnil;
|
701
|
+
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_RECV);
|
702
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
703
|
+
io_uring_prep_recv(sqe, fptr->fd, buf, len, 0);
|
704
|
+
|
705
|
+
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
706
|
+
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
707
|
+
RAISE_IF_EXCEPTION(resume_value);
|
708
|
+
if (!ctx->completed) return resume_value;
|
709
|
+
RB_GC_GUARD(resume_value);
|
710
|
+
|
711
|
+
if (result < 0)
|
712
|
+
rb_syserr_fail(-result, strerror(-result));
|
713
|
+
else if (!result)
|
714
|
+
break; // EOF
|
715
|
+
else {
|
716
|
+
total = result;
|
717
|
+
READ_LOOP_PASS_STR_TO_RECEIVER(receiver, method_id);
|
718
|
+
}
|
719
|
+
}
|
720
|
+
|
721
|
+
RB_GC_GUARD(str);
|
722
|
+
return io;
|
723
|
+
}
|
724
|
+
|
725
|
+
VALUE Backend_send(VALUE self, VALUE io, VALUE str, VALUE flags) {
|
608
726
|
Backend_t *backend;
|
609
727
|
rb_io_t *fptr;
|
610
728
|
VALUE underlying_io;
|
@@ -614,16 +732,18 @@ VALUE Backend_send(VALUE self, VALUE io, VALUE str) {
|
|
614
732
|
GetBackend(self, backend);
|
615
733
|
io = rb_io_get_write_io(io);
|
616
734
|
GetOpenFile(io, fptr);
|
735
|
+
io_unset_nonblock(fptr, io);
|
617
736
|
|
618
737
|
char *buf = StringValuePtr(str);
|
619
738
|
long len = RSTRING_LEN(str);
|
620
739
|
long left = len;
|
740
|
+
int flags_int = NUM2INT(flags);
|
621
741
|
|
622
742
|
while (left > 0) {
|
623
743
|
VALUE resume_value = Qnil;
|
624
744
|
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_SEND);
|
625
745
|
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
626
|
-
io_uring_prep_send(sqe, fptr->fd, buf, left,
|
746
|
+
io_uring_prep_send(sqe, fptr->fd, buf, left, flags_int);
|
627
747
|
|
628
748
|
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
629
749
|
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
@@ -651,6 +771,8 @@ VALUE io_uring_backend_accept(Backend_t *backend, VALUE server_socket, VALUE soc
|
|
651
771
|
if (underlying_sock != Qnil) server_socket = underlying_sock;
|
652
772
|
|
653
773
|
GetOpenFile(server_socket, fptr);
|
774
|
+
io_unset_nonblock(fptr, server_socket);
|
775
|
+
|
654
776
|
while (1) {
|
655
777
|
VALUE resume_value = Qnil;
|
656
778
|
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_ACCEPT);
|
@@ -704,6 +826,60 @@ VALUE Backend_accept_loop(VALUE self, VALUE server_socket, VALUE socket_class) {
|
|
704
826
|
return self;
|
705
827
|
}
|
706
828
|
|
829
|
+
VALUE io_uring_backend_splice(Backend_t *backend, VALUE src, VALUE dest, VALUE maxlen, int loop) {
|
830
|
+
rb_io_t *src_fptr;
|
831
|
+
rb_io_t *dest_fptr;
|
832
|
+
VALUE underlying_io;
|
833
|
+
int total = 0;
|
834
|
+
|
835
|
+
underlying_io = rb_ivar_get(src, ID_ivar_io);
|
836
|
+
if (underlying_io != Qnil) src = underlying_io;
|
837
|
+
GetOpenFile(src, src_fptr);
|
838
|
+
io_unset_nonblock(src_fptr, src);
|
839
|
+
|
840
|
+
underlying_io = rb_ivar_get(dest, ID_ivar_io);
|
841
|
+
if (underlying_io != Qnil) dest = underlying_io;
|
842
|
+
dest = rb_io_get_write_io(dest);
|
843
|
+
GetOpenFile(dest, dest_fptr);
|
844
|
+
io_unset_nonblock(dest_fptr, dest);
|
845
|
+
|
846
|
+
VALUE resume_value = Qnil;
|
847
|
+
|
848
|
+
while (1) {
|
849
|
+
op_context_t *ctx = OP_CONTEXT_ACQUIRE(&backend->store, OP_SPLICE);
|
850
|
+
struct io_uring_sqe *sqe = io_uring_get_sqe(&backend->ring);
|
851
|
+
io_uring_prep_splice(sqe, src_fptr->fd, -1, dest_fptr->fd, -1, NUM2INT(maxlen), 0);
|
852
|
+
|
853
|
+
int result = io_uring_backend_defer_submit_and_await(backend, sqe, ctx, &resume_value);
|
854
|
+
OP_CONTEXT_RELEASE(&backend->store, ctx);
|
855
|
+
RAISE_IF_EXCEPTION(resume_value);
|
856
|
+
if (!ctx->completed) return resume_value;
|
857
|
+
|
858
|
+
if (result < 0)
|
859
|
+
rb_syserr_fail(-result, strerror(-result));
|
860
|
+
|
861
|
+
total += result;
|
862
|
+
if (result == 0 || !loop) return INT2NUM(total);
|
863
|
+
}
|
864
|
+
|
865
|
+
RB_GC_GUARD(resume_value);
|
866
|
+
}
|
867
|
+
|
868
|
+
VALUE Backend_splice(VALUE self, VALUE src, VALUE dest, VALUE maxlen) {
|
869
|
+
Backend_t *backend;
|
870
|
+
GetBackend(self, backend);
|
871
|
+
|
872
|
+
return io_uring_backend_splice(backend, src, dest, maxlen, 0);
|
873
|
+
}
|
874
|
+
|
875
|
+
VALUE Backend_splice_to_eof(VALUE self, VALUE src, VALUE dest, VALUE chunksize) {
|
876
|
+
Backend_t *backend;
|
877
|
+
GetBackend(self, backend);
|
878
|
+
|
879
|
+
return io_uring_backend_splice(backend, src, dest, chunksize, 1);
|
880
|
+
}
|
881
|
+
|
882
|
+
|
707
883
|
VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
708
884
|
Backend_t *backend;
|
709
885
|
rb_io_t *fptr;
|
@@ -714,6 +890,7 @@ VALUE Backend_connect(VALUE self, VALUE sock, VALUE host, VALUE port) {
|
|
714
890
|
|
715
891
|
GetBackend(self, backend);
|
716
892
|
GetOpenFile(sock, fptr);
|
893
|
+
io_unset_nonblock(fptr, sock);
|
717
894
|
|
718
895
|
addr.sin_family = AF_INET;
|
719
896
|
addr.sin_addr.s_addr = inet_addr(host_buf);
|
@@ -740,6 +917,7 @@ VALUE Backend_wait_io(VALUE self, VALUE io, VALUE write) {
|
|
740
917
|
if (underlying_io != Qnil) io = underlying_io;
|
741
918
|
GetBackend(self, backend);
|
742
919
|
GetOpenFile(io, fptr);
|
920
|
+
io_unset_nonblock(fptr, io);
|
743
921
|
|
744
922
|
VALUE resume_value = io_uring_backend_wait_fd(backend, fptr->fd, RTEST(write));
|
745
923
|
RAISE_IF_EXCEPTION(resume_value);
|
@@ -811,18 +989,6 @@ VALUE Backend_timer_loop(VALUE self, VALUE interval) {
|
|
811
989
|
}
|
812
990
|
}
|
813
991
|
|
814
|
-
VALUE Backend_timeout_safe(VALUE arg) {
|
815
|
-
return rb_yield(arg);
|
816
|
-
}
|
817
|
-
|
818
|
-
VALUE Backend_timeout_rescue(VALUE arg, VALUE exception) {
|
819
|
-
return exception;
|
820
|
-
}
|
821
|
-
|
822
|
-
VALUE Backend_timeout_ensure_safe(VALUE arg) {
|
823
|
-
return rb_rescue2(Backend_timeout_safe, Qnil, Backend_timeout_rescue, Qnil, rb_eException, (VALUE)0);
|
824
|
-
}
|
825
|
-
|
826
992
|
struct Backend_timeout_ctx {
|
827
993
|
Backend_t *backend;
|
828
994
|
op_context_t *ctx;
|
@@ -861,7 +1027,6 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
861
1027
|
ctx->resume_value = timeout;
|
862
1028
|
io_uring_prep_timeout(sqe, &ts, 0, 0);
|
863
1029
|
io_uring_sqe_set_data(sqe, ctx);
|
864
|
-
io_uring_sqe_set_flags(sqe, IOSQE_ASYNC);
|
865
1030
|
io_uring_backend_defer_submit(backend);
|
866
1031
|
|
867
1032
|
struct Backend_timeout_ctx timeout_ctx = {backend, ctx};
|
@@ -879,19 +1044,28 @@ VALUE Backend_timeout(int argc, VALUE *argv, VALUE self) {
|
|
879
1044
|
}
|
880
1045
|
|
881
1046
|
VALUE Backend_waitpid(VALUE self, VALUE pid) {
|
882
|
-
Backend_t *backend;
|
883
1047
|
int pid_int = NUM2INT(pid);
|
884
1048
|
int fd = pidfd_open(pid_int, 0);
|
885
|
-
GetBackend(self, backend);
|
886
|
-
|
887
|
-
VALUE resume_value = io_uring_backend_wait_fd(backend, fd, 0);
|
888
|
-
close(fd);
|
889
1049
|
|
890
|
-
|
891
|
-
|
1050
|
+
if (fd >= 0) {
|
1051
|
+
Backend_t *backend;
|
1052
|
+
GetBackend(self, backend);
|
892
1053
|
|
1054
|
+
VALUE resume_value = io_uring_backend_wait_fd(backend, fd, 0);
|
1055
|
+
close(fd);
|
1056
|
+
RAISE_IF_EXCEPTION(resume_value);
|
1057
|
+
RB_GC_GUARD(resume_value);
|
1058
|
+
}
|
1059
|
+
|
893
1060
|
int status;
|
894
1061
|
pid_t ret = waitpid(pid_int, &status, WNOHANG);
|
1062
|
+
if (ret < 0) {
|
1063
|
+
int e = errno;
|
1064
|
+
if (e == ECHILD)
|
1065
|
+
ret = pid_int;
|
1066
|
+
else
|
1067
|
+
rb_syserr_fail(e, strerror(e));
|
1068
|
+
}
|
895
1069
|
return rb_ary_new_from_args(2, INT2NUM(ret), INT2NUM(WEXITSTATUS(status)));
|
896
1070
|
}
|
897
1071
|
|
@@ -918,7 +1092,7 @@ VALUE Backend_kind(VALUE self) {
|
|
918
1092
|
}
|
919
1093
|
|
920
1094
|
void Init_Backend() {
|
921
|
-
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend",
|
1095
|
+
VALUE cBackend = rb_define_class_under(mPolyphony, "Backend", rb_cObject);
|
922
1096
|
rb_define_alloc_func(cBackend, Backend_allocate);
|
923
1097
|
|
924
1098
|
rb_define_method(cBackend, "initialize", Backend_initialize, 0);
|
@@ -927,24 +1101,33 @@ void Init_Backend() {
|
|
927
1101
|
|
928
1102
|
rb_define_method(cBackend, "poll", Backend_poll, 3);
|
929
1103
|
rb_define_method(cBackend, "break", Backend_wakeup, 0);
|
1104
|
+
rb_define_method(cBackend, "kind", Backend_kind, 0);
|
930
1105
|
|
1106
|
+
rb_define_method(cBackend, "accept", Backend_accept, 2);
|
1107
|
+
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
1108
|
+
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
1109
|
+
rb_define_method(cBackend, "feed_loop", Backend_feed_loop, 3);
|
931
1110
|
rb_define_method(cBackend, "read", Backend_read, 4);
|
932
1111
|
rb_define_method(cBackend, "read_loop", Backend_read_loop, 1);
|
933
|
-
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
934
1112
|
rb_define_method(cBackend, "recv", Backend_recv, 3);
|
1113
|
+
rb_define_method(cBackend, "recv_feed_loop", Backend_recv_feed_loop, 3);
|
935
1114
|
rb_define_method(cBackend, "recv_loop", Backend_recv_loop, 1);
|
936
|
-
rb_define_method(cBackend, "send", Backend_send,
|
937
|
-
rb_define_method(cBackend, "
|
938
|
-
rb_define_method(cBackend, "accept_loop", Backend_accept_loop, 2);
|
939
|
-
rb_define_method(cBackend, "connect", Backend_connect, 3);
|
940
|
-
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1115
|
+
rb_define_method(cBackend, "send", Backend_send, 3);
|
1116
|
+
rb_define_method(cBackend, "sendv", Backend_sendv, 3);
|
941
1117
|
rb_define_method(cBackend, "sleep", Backend_sleep, 1);
|
942
|
-
rb_define_method(cBackend, "
|
1118
|
+
rb_define_method(cBackend, "splice", Backend_splice, 3);
|
1119
|
+
rb_define_method(cBackend, "splice_to_eof", Backend_splice_to_eof, 3);
|
943
1120
|
rb_define_method(cBackend, "timeout", Backend_timeout, -1);
|
944
|
-
rb_define_method(cBackend, "
|
1121
|
+
rb_define_method(cBackend, "timer_loop", Backend_timer_loop, 1);
|
945
1122
|
rb_define_method(cBackend, "wait_event", Backend_wait_event, 1);
|
1123
|
+
rb_define_method(cBackend, "wait_io", Backend_wait_io, 2);
|
1124
|
+
rb_define_method(cBackend, "waitpid", Backend_waitpid, 1);
|
1125
|
+
rb_define_method(cBackend, "write", Backend_write_m, -1);
|
946
1126
|
|
947
|
-
|
1127
|
+
|
1128
|
+
#ifdef POLYPHONY_UNSET_NONBLOCK
|
1129
|
+
ID_ivar_is_nonblocking = rb_intern("@is_nonblocking");
|
1130
|
+
#endif
|
948
1131
|
|
949
1132
|
SYM_io_uring = ID2SYM(rb_intern("io_uring"));
|
950
1133
|
}
|