polyphony 0.51.0 → 0.54.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/.github/workflows/test.yml +2 -2
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +7 -68
- data/TODO.md +37 -6
- data/examples/core/forking.rb +2 -2
- data/examples/core/queue.rb +19 -0
- data/examples/io/echo_server.rb +1 -0
- data/examples/io/https_server.rb +30 -0
- data/examples/io/tcp_proxy.rb +2 -2
- data/ext/polyphony/backend_common.h +29 -6
- data/ext/polyphony/backend_io_uring.c +125 -23
- 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 +309 -21
- 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 +2 -2
- data/lib/polyphony/core/global_api.rb +5 -5
- data/lib/polyphony/core/sync.rb +9 -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 +20 -25
- data/lib/polyphony/extensions/openssl.rb +28 -21
- data/lib/polyphony/extensions/socket.rb +51 -54
- 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 +33 -2
- data/test/test_kernel.rb +1 -1
- data/test/test_signal.rb +1 -1
- data/test/test_socket.rb +27 -0
- data/test/test_sync.rb +43 -0
- data/test/test_thread.rb +4 -0
- data/test/test_timer.rb +1 -1
- metadata +10 -49
@@ -55,7 +55,7 @@ module ::Process
|
|
55
55
|
class << self
|
56
56
|
alias_method :orig_detach, :detach
|
57
57
|
def detach(pid)
|
58
|
-
fiber = spin {
|
58
|
+
fiber = spin { Polyphony.backend_waitpid(pid) }
|
59
59
|
fiber.define_singleton_method(:pid) { pid }
|
60
60
|
fiber
|
61
61
|
end
|
@@ -101,7 +101,7 @@ class ::IO
|
|
101
101
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
102
102
|
|
103
103
|
@read_buffer ||= +''
|
104
|
-
|
104
|
+
Polyphony.backend_read(self, @read_buffer, 8192, false)
|
105
105
|
return @read_buffer.slice!(0) if !@read_buffer.empty?
|
106
106
|
|
107
107
|
nil
|
@@ -110,7 +110,7 @@ class ::IO
|
|
110
110
|
alias_method :orig_read, :read
|
111
111
|
def read(len = nil)
|
112
112
|
@read_buffer ||= +''
|
113
|
-
result =
|
113
|
+
result = Polyphony.backend_read(self, @read_buffer, len, true)
|
114
114
|
return nil unless result
|
115
115
|
|
116
116
|
already_read = @read_buffer
|
@@ -120,7 +120,7 @@ class ::IO
|
|
120
120
|
|
121
121
|
alias_method :orig_readpartial, :read
|
122
122
|
def readpartial(len, str = +'')
|
123
|
-
result =
|
123
|
+
result = Polyphony.backend_read(self, str, len, false)
|
124
124
|
raise EOFError unless result
|
125
125
|
|
126
126
|
result
|
@@ -128,12 +128,12 @@ class ::IO
|
|
128
128
|
|
129
129
|
alias_method :orig_write, :write
|
130
130
|
def write(str, *args)
|
131
|
-
|
131
|
+
Polyphony.backend_write(self, str, *args)
|
132
132
|
end
|
133
133
|
|
134
134
|
alias_method :orig_write_chevron, :<<
|
135
135
|
def <<(str)
|
136
|
-
|
136
|
+
Polyphony.backend_write(self, str)
|
137
137
|
self
|
138
138
|
end
|
139
139
|
|
@@ -217,34 +217,21 @@ class ::IO
|
|
217
217
|
end
|
218
218
|
|
219
219
|
def read_loop(&block)
|
220
|
-
|
220
|
+
Polyphony.backend_read_loop(self, &block)
|
221
221
|
end
|
222
222
|
|
223
|
-
def feed_loop(receiver, method, &block)
|
224
|
-
|
223
|
+
def feed_loop(receiver, method = :call, &block)
|
224
|
+
Polyphony.backend_feed_loop(self, receiver, method, &block)
|
225
225
|
end
|
226
226
|
|
227
|
-
# alias_method :orig_read, :read
|
228
|
-
# def read(length = nil, outbuf = nil)
|
229
|
-
# if length
|
230
|
-
# return outbuf ? readpartial(length) : readpartial(length, outbuf)
|
231
|
-
# end
|
232
|
-
|
233
|
-
# until eof?
|
234
|
-
# outbuf ||= +''
|
235
|
-
# outbuf << readpartial(8192)
|
236
|
-
# end
|
237
|
-
# outbuf
|
238
|
-
# end
|
239
|
-
|
240
227
|
def wait_readable(timeout = nil)
|
241
228
|
if timeout
|
242
229
|
move_on_after(timeout) do
|
243
|
-
|
230
|
+
Polyphony.backend_wait_io(self, false)
|
244
231
|
self
|
245
232
|
end
|
246
233
|
else
|
247
|
-
|
234
|
+
Polyphony.backend_wait_io(self, false)
|
248
235
|
self
|
249
236
|
end
|
250
237
|
end
|
@@ -252,12 +239,20 @@ class ::IO
|
|
252
239
|
def wait_writable(timeout = nil)
|
253
240
|
if timeout
|
254
241
|
move_on_after(timeout) do
|
255
|
-
|
242
|
+
Polyphony.backend_wait_io(self, true)
|
256
243
|
self
|
257
244
|
end
|
258
245
|
else
|
259
|
-
|
246
|
+
Polyphony.backend_wait_io(self, true)
|
260
247
|
self
|
261
248
|
end
|
262
249
|
end
|
250
|
+
|
251
|
+
def splice(src, maxlen)
|
252
|
+
Polyphony.backend_splice(src, self, maxlen)
|
253
|
+
end
|
254
|
+
|
255
|
+
def splice_to_eof(src, chunksize = 8192)
|
256
|
+
Polyphony.backend_splice_to_eof(src, self, chunksize)
|
257
|
+
end
|
263
258
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'openssl'
|
4
4
|
require_relative './socket'
|
5
5
|
|
6
|
-
#
|
6
|
+
# OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
|
7
7
|
class ::OpenSSL::SSL::SSLSocket
|
8
8
|
alias_method :orig_initialize, :initialize
|
9
9
|
def initialize(socket, context = nil)
|
@@ -23,22 +23,12 @@ class ::OpenSSL::SSL::SSLSocket
|
|
23
23
|
io.reuse_addr
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
when :wait_writable then Thread.current.backend.wait_io(io, true)
|
33
|
-
else
|
34
|
-
return result
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def accept_loop
|
40
|
-
while true
|
41
|
-
yield accept
|
26
|
+
def fill_rbuff
|
27
|
+
data = self.sysread(BLOCK_SIZE)
|
28
|
+
if data
|
29
|
+
@rbuffer << data
|
30
|
+
else
|
31
|
+
@eof = true
|
42
32
|
end
|
43
33
|
end
|
44
34
|
|
@@ -46,8 +36,8 @@ class ::OpenSSL::SSL::SSLSocket
|
|
46
36
|
def sysread(maxlen, buf = +'')
|
47
37
|
while true
|
48
38
|
case (result = read_nonblock(maxlen, buf, exception: false))
|
49
|
-
when :wait_readable then
|
50
|
-
when :wait_writable then
|
39
|
+
when :wait_readable then Polyphony.backend_wait_io(io, false)
|
40
|
+
when :wait_writable then Polyphony.backend_wait_io(io, true)
|
51
41
|
else return result
|
52
42
|
end
|
53
43
|
end
|
@@ -57,8 +47,8 @@ class ::OpenSSL::SSL::SSLSocket
|
|
57
47
|
def syswrite(buf)
|
58
48
|
while true
|
59
49
|
case (result = write_nonblock(buf, exception: false))
|
60
|
-
when :wait_readable then
|
61
|
-
when :wait_writable then
|
50
|
+
when :wait_readable then Polyphony.backend_wait_io(io, false)
|
51
|
+
when :wait_writable then Polyphony.backend_wait_io(io, true)
|
62
52
|
else
|
63
53
|
return result
|
64
54
|
end
|
@@ -84,4 +74,21 @@ class ::OpenSSL::SSL::SSLSocket
|
|
84
74
|
yield data
|
85
75
|
end
|
86
76
|
end
|
77
|
+
alias_method :recv_loop, :read_loop
|
78
|
+
|
79
|
+
alias_method :orig_peeraddr, :peeraddr
|
80
|
+
def peeraddr(_ = nil)
|
81
|
+
orig_peeraddr
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# OpenSSL socket helper methods (to make it compatible with Socket API) and overrides
|
86
|
+
class ::OpenSSL::SSL::SSLServer
|
87
|
+
def accept_loop(ignore_errors = true)
|
88
|
+
loop do
|
89
|
+
yield accept
|
90
|
+
rescue SystemCallError, StandardError => e
|
91
|
+
raise e unless ignore_errors
|
92
|
+
end
|
93
|
+
end
|
87
94
|
end
|
@@ -8,31 +8,31 @@ require_relative '../core/thread_pool'
|
|
8
8
|
# Socket overrides (eventually rewritten in C)
|
9
9
|
class ::Socket
|
10
10
|
def accept
|
11
|
-
|
11
|
+
Polyphony.backend_accept(self, TCPSocket)
|
12
12
|
end
|
13
13
|
|
14
14
|
def accept_loop(&block)
|
15
|
-
|
15
|
+
Polyphony.backend_accept_loop(self, TCPSocket, &block)
|
16
16
|
end
|
17
17
|
|
18
18
|
NO_EXCEPTION = { exception: false }.freeze
|
19
19
|
|
20
20
|
def connect(addr)
|
21
21
|
addr = Addrinfo.new(addr) if addr.is_a?(String)
|
22
|
-
|
22
|
+
Polyphony.backend_connect(self, addr.ip_address, addr.ip_port)
|
23
23
|
end
|
24
24
|
|
25
25
|
def recv(maxlen, flags = 0, outbuf = nil)
|
26
|
-
|
26
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
27
27
|
end
|
28
28
|
|
29
29
|
def recv_loop(&block)
|
30
|
-
|
30
|
+
Polyphony.backend_recv_loop(self, &block)
|
31
31
|
end
|
32
32
|
alias_method :read_loop, :recv_loop
|
33
33
|
|
34
|
-
def feed_loop(receiver, method, &block)
|
35
|
-
|
34
|
+
def feed_loop(receiver, method = :call, &block)
|
35
|
+
Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
|
36
36
|
end
|
37
37
|
|
38
38
|
def recvfrom(maxlen, flags = 0)
|
@@ -41,28 +41,27 @@ class ::Socket
|
|
41
41
|
result = recvfrom_nonblock(maxlen, flags, @read_buffer, **NO_EXCEPTION)
|
42
42
|
case result
|
43
43
|
when nil then raise IOError
|
44
|
-
when :wait_readable then
|
44
|
+
when :wait_readable then Polyphony.backend_wait_io(self, false)
|
45
45
|
else
|
46
46
|
return result
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
def send(mesg, flags
|
52
|
-
|
53
|
-
end
|
51
|
+
# def send(mesg, flags)
|
52
|
+
# Polyphony.backend_send(self, mesg, flags)
|
53
|
+
# end
|
54
54
|
|
55
|
-
def write(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
alias_method :<<, :write
|
55
|
+
# def write(*args)
|
56
|
+
# Polyphony.backend_sendv(self, args, 0)
|
57
|
+
# end
|
58
|
+
|
59
|
+
# def <<(mesg)
|
60
|
+
# Polyphony.backend_send(self, mesg, 0)
|
61
|
+
# end
|
63
62
|
|
64
63
|
def readpartial(maxlen, str = +'')
|
65
|
-
|
64
|
+
Polyphony.backend_recv(self, str, maxlen)
|
66
65
|
end
|
67
66
|
|
68
67
|
ZERO_LINGER = [0, 0].pack('ii').freeze
|
@@ -142,34 +141,33 @@ class ::TCPSocket
|
|
142
141
|
end
|
143
142
|
|
144
143
|
def recv(maxlen, flags = 0, outbuf = nil)
|
145
|
-
|
144
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
146
145
|
end
|
147
146
|
|
148
147
|
def recv_loop(&block)
|
149
|
-
|
148
|
+
Polyphony.backend_recv_loop(self, &block)
|
150
149
|
end
|
151
150
|
alias_method :read_loop, :recv_loop
|
152
151
|
|
153
|
-
def feed_loop(receiver, method, &block)
|
154
|
-
|
152
|
+
def feed_loop(receiver, method = :call, &block)
|
153
|
+
Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
|
155
154
|
end
|
156
155
|
|
157
|
-
def send(mesg, flags
|
158
|
-
|
159
|
-
end
|
156
|
+
# def send(mesg, flags)
|
157
|
+
# Polyphony.backend_send(self, mesg, flags)
|
158
|
+
# end
|
160
159
|
|
161
|
-
def write(
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end
|
168
|
-
alias_method :<<, :write
|
160
|
+
# def write(*args)
|
161
|
+
# Polyphony.backend_sendv(self, args, 0)
|
162
|
+
# end
|
163
|
+
|
164
|
+
# def <<(mesg)
|
165
|
+
# Polyphony.backend_send(self, mesg, 0)
|
166
|
+
# end
|
169
167
|
|
170
168
|
def readpartial(maxlen, str = nil)
|
171
169
|
@read_buffer ||= +''
|
172
|
-
result =
|
170
|
+
result = Polyphony.backend_recv(self, @read_buffer, maxlen)
|
173
171
|
raise EOFError unless result
|
174
172
|
|
175
173
|
if str
|
@@ -200,12 +198,12 @@ class ::TCPServer
|
|
200
198
|
|
201
199
|
alias_method :orig_accept, :accept
|
202
200
|
def accept
|
203
|
-
|
201
|
+
Polyphony.backend_accept(@io, TCPSocket)
|
204
202
|
# @io.accept
|
205
203
|
end
|
206
204
|
|
207
205
|
def accept_loop(&block)
|
208
|
-
|
206
|
+
Polyphony.backend_accept_loop(@io, TCPSocket, &block)
|
209
207
|
end
|
210
208
|
|
211
209
|
alias_method :orig_close, :close
|
@@ -217,44 +215,43 @@ end
|
|
217
215
|
class ::UNIXServer
|
218
216
|
alias_method :orig_accept, :accept
|
219
217
|
def accept
|
220
|
-
|
218
|
+
Polyphony.backend_accept(self, UNIXSocket)
|
221
219
|
end
|
222
220
|
|
223
221
|
def accept_loop(&block)
|
224
|
-
|
222
|
+
Polyphony.backend_accept_loop(self, UNIXSocket, &block)
|
225
223
|
end
|
226
224
|
end
|
227
225
|
|
228
226
|
class ::UNIXSocket
|
229
227
|
def recv(maxlen, flags = 0, outbuf = nil)
|
230
|
-
|
228
|
+
Polyphony.backend_recv(self, outbuf || +'', maxlen)
|
231
229
|
end
|
232
230
|
|
233
231
|
def recv_loop(&block)
|
234
|
-
|
232
|
+
Polyphony.backend_recv_loop(self, &block)
|
235
233
|
end
|
236
234
|
alias_method :read_loop, :recv_loop
|
237
235
|
|
238
|
-
def feed_loop(receiver, method, &block)
|
239
|
-
|
236
|
+
def feed_loop(receiver, method = :call, &block)
|
237
|
+
Polyphony.backend_recv_feed_loop(self, receiver, method, &block)
|
240
238
|
end
|
241
239
|
|
242
|
-
def send(mesg, flags
|
243
|
-
|
240
|
+
def send(mesg, flags)
|
241
|
+
Polyphony.backend_send(self, mesg, flags)
|
244
242
|
end
|
245
243
|
|
246
|
-
def write(
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
244
|
+
def write(*args)
|
245
|
+
Polyphony.backend_sendv(self, args, 0)
|
246
|
+
end
|
247
|
+
|
248
|
+
def <<(mesg)
|
249
|
+
Polyphony.backend_send(self, mesg, 0)
|
252
250
|
end
|
253
|
-
alias_method :<<, :write
|
254
251
|
|
255
252
|
def readpartial(maxlen, str = nil)
|
256
253
|
@read_buffer ||= +''
|
257
|
-
result =
|
254
|
+
result = Polyphony.backend_recv(self, @read_buffer, maxlen)
|
258
255
|
raise EOFError unless result
|
259
256
|
|
260
257
|
if str
|
data/lib/polyphony/version.rb
CHANGED
data/polyphony.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.required_ruby_version = '>= 2.6'
|
23
23
|
|
24
24
|
s.add_development_dependency 'rake-compiler', '1.1.1'
|
25
|
-
s.add_development_dependency 'minitest', '5.
|
25
|
+
s.add_development_dependency 'minitest', '5.14.4'
|
26
26
|
s.add_development_dependency 'minitest-reporters', '1.4.2'
|
27
27
|
s.add_development_dependency 'simplecov', '0.17.1'
|
28
28
|
s.add_development_dependency 'rubocop', '0.85.1'
|
@@ -37,9 +37,10 @@ Gem::Specification.new do |s|
|
|
37
37
|
s.add_development_dependency 'mysql2', '0.5.3'
|
38
38
|
s.add_development_dependency 'sequel', '5.34.0'
|
39
39
|
s.add_development_dependency 'httparty', '0.17.1'
|
40
|
+
s.add_development_dependency 'localhost', '~>1.1.4'
|
40
41
|
|
41
|
-
s.add_development_dependency 'jekyll', '~>3.8.6'
|
42
|
-
s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'
|
43
|
-
s.add_development_dependency 'jekyll-seo-tag', '~>2.6.1'
|
44
|
-
s.add_development_dependency 'just-the-docs', '~>0.3.0'
|
42
|
+
# s.add_development_dependency 'jekyll', '~>3.8.6'
|
43
|
+
# s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'
|
44
|
+
# s.add_development_dependency 'jekyll-seo-tag', '~>2.6.1'
|
45
|
+
# s.add_development_dependency 'just-the-docs', '~>0.3.0'
|
45
46
|
end
|
data/test/helper.rb
CHANGED