polyphony 1.1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.github/workflows/test_io_uring.yml +1 -1
- data/.rubocop.yml +16 -8
- data/CHANGELOG.md +9 -0
- data/README.md +2 -1
- data/docs/advanced-io.md +9 -1
- data/docs/cancellation.md +213 -0
- data/docs/readme.md +2 -1
- data/examples/core/enumerator.rb +92 -0
- data/examples/io/https_server_sni_2.rb +1 -1
- data/ext/polyphony/backend_common.c +11 -0
- data/ext/polyphony/backend_common.h +2 -0
- data/ext/polyphony/backend_io_uring.c +1 -1
- data/ext/polyphony/backend_libev.c +1 -1
- data/ext/polyphony/polyphony.h +3 -1
- data/lib/polyphony/core/debug.rb +24 -29
- data/lib/polyphony/core/exceptions.rb +0 -3
- data/lib/polyphony/core/sync.rb +0 -3
- data/lib/polyphony/core/thread_pool.rb +1 -5
- data/lib/polyphony/core/throttler.rb +0 -1
- data/lib/polyphony/core/timer.rb +7 -9
- data/lib/polyphony/extensions/exception.rb +0 -1
- data/lib/polyphony/extensions/fiber.rb +41 -28
- data/lib/polyphony/extensions/io.rb +86 -93
- data/lib/polyphony/extensions/kernel.rb +52 -16
- data/lib/polyphony/extensions/object.rb +7 -6
- data/lib/polyphony/extensions/openssl.rb +6 -8
- data/lib/polyphony/extensions/pipe.rb +5 -7
- data/lib/polyphony/extensions/socket.rb +28 -37
- data/lib/polyphony/extensions/thread.rb +2 -4
- data/lib/polyphony/extensions/timeout.rb +0 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +4 -7
- data/polyphony.gemspec +1 -1
- data/test/test_fiber.rb +6 -6
- data/test/test_global_api.rb +3 -3
- data/test/test_io.rb +2 -2
- data/test/test_socket.rb +2 -2
- data/test/test_supervise.rb +1 -1
- metadata +5 -3
@@ -80,7 +80,6 @@ class ::IO
|
|
80
80
|
# @!visibility private
|
81
81
|
alias_method :orig_popen, :popen
|
82
82
|
|
83
|
-
|
84
83
|
# @!visibility private
|
85
84
|
def popen(cmd, mode = 'r')
|
86
85
|
return orig_popen(cmd, mode) unless block_given?
|
@@ -163,7 +162,6 @@ class ::IO
|
|
163
162
|
# @!visibility private
|
164
163
|
alias_method :orig_getbyte, :getbyte
|
165
164
|
|
166
|
-
|
167
165
|
# @!visibility private
|
168
166
|
def getbyte
|
169
167
|
char = getc
|
@@ -173,7 +171,6 @@ class ::IO
|
|
173
171
|
# @!visibility private
|
174
172
|
alias_method :orig_getc, :getc
|
175
173
|
|
176
|
-
|
177
174
|
# @!visibility private
|
178
175
|
def getc
|
179
176
|
return @read_buffer.slice!(0) if @read_buffer && !@read_buffer.empty?
|
@@ -186,12 +183,12 @@ class ::IO
|
|
186
183
|
end
|
187
184
|
|
188
185
|
# @!visibility private
|
189
|
-
def ungetc(
|
190
|
-
|
186
|
+
def ungetc(chr)
|
187
|
+
chr = chr.chr if chr.is_a?(Integer)
|
191
188
|
if @read_buffer
|
192
|
-
@read_buffer.prepend(
|
189
|
+
@read_buffer.prepend(chr)
|
193
190
|
else
|
194
|
-
@read_buffer = +
|
191
|
+
@read_buffer = +chr
|
195
192
|
end
|
196
193
|
end
|
197
194
|
alias_method :ungetbyte, :ungetc
|
@@ -199,14 +196,10 @@ class ::IO
|
|
199
196
|
# @!visibility private
|
200
197
|
alias_method :orig_read, :read
|
201
198
|
|
202
|
-
|
203
199
|
# @!visibility private
|
204
|
-
def read(len = nil, buf = nil,
|
200
|
+
def read(len = nil, buf = nil, buffer_pos: 0)
|
205
201
|
return '' if len == 0
|
206
|
-
|
207
|
-
if buf
|
208
|
-
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
209
|
-
end
|
202
|
+
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
210
203
|
|
211
204
|
@read_buffer ||= +''
|
212
205
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
@@ -221,7 +214,7 @@ class ::IO
|
|
221
214
|
alias_method :orig_readpartial, :read
|
222
215
|
|
223
216
|
# @!visibility private
|
224
|
-
def readpartial(len, str = +'', buffer_pos
|
217
|
+
def readpartial(len, str = +'', buffer_pos: 0, raise_on_eof: true)
|
225
218
|
result = Polyphony.backend_read(self, str, len, false, buffer_pos)
|
226
219
|
raise EOFError if !result && raise_on_eof
|
227
220
|
|
@@ -262,7 +255,7 @@ class ::IO
|
|
262
255
|
idx = @read_buffer.index(sep)
|
263
256
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
264
257
|
|
265
|
-
result = readpartial(8192, @read_buffer, -1)
|
258
|
+
result = readpartial(8192, @read_buffer, buffer_pos: -1)
|
266
259
|
return nil unless result
|
267
260
|
end
|
268
261
|
rescue EOFError
|
@@ -287,7 +280,7 @@ class ::IO
|
|
287
280
|
yield line
|
288
281
|
end
|
289
282
|
|
290
|
-
result = readpartial(8192, @read_buffer, -1)
|
283
|
+
result = readpartial(8192, @read_buffer, buffer_pos: -1)
|
291
284
|
return self if !result
|
292
285
|
end
|
293
286
|
rescue EOFError
|
@@ -306,7 +299,7 @@ class ::IO
|
|
306
299
|
# @!visibility private
|
307
300
|
LINEFEED = "\n"
|
308
301
|
# @!visibility private
|
309
|
-
LINEFEED_RE = /\n
|
302
|
+
LINEFEED_RE = /\n$/
|
310
303
|
|
311
304
|
# @!visibility private
|
312
305
|
alias_method :orig_puts, :puts
|
@@ -351,97 +344,97 @@ class ::IO
|
|
351
344
|
|
352
345
|
# @!visibility private
|
353
346
|
def write_nonblock(string, _options = {})
|
354
|
-
|
355
|
-
end
|
356
|
-
|
357
|
-
# @!visibility private
|
358
|
-
alias_method :orig_read_nonblock, :read_nonblock
|
347
|
+
write(string)
|
348
|
+
end
|
359
349
|
|
360
|
-
# @!visibility private
|
361
|
-
|
362
|
-
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
363
|
-
end
|
350
|
+
# @!visibility private
|
351
|
+
alias_method :orig_read_nonblock, :read_nonblock
|
364
352
|
|
365
|
-
#
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
# @yield [String] read data
|
370
|
-
# @return [IO] self
|
371
|
-
def read_loop(maxlen = 8192, &block)
|
372
|
-
Polyphony.backend_read_loop(self, maxlen, &block)
|
373
|
-
end
|
353
|
+
# @!visibility private
|
354
|
+
def read_nonblock(maxlen, buf = nil, _options = nil)
|
355
|
+
buf ? readpartial(maxlen, buf) : readpartial(maxlen)
|
356
|
+
end
|
374
357
|
|
375
|
-
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
380
|
-
#
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
# io.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
|
385
|
-
#
|
386
|
-
# @param receiver [any] receiver object
|
387
|
-
# @param method [Symbol] method to call
|
388
|
-
# @return [IO] self
|
389
|
-
def feed_loop(receiver, method = :call, &block)
|
390
|
-
Polyphony.backend_feed_loop(self, receiver, method, &block)
|
391
|
-
end
|
358
|
+
# Reads up to `maxlen` bytes at a time in an infinite loop. Read data
|
359
|
+
# will be passed to the given block.
|
360
|
+
#
|
361
|
+
# @param maxlen [Integer] maximum bytes to receive
|
362
|
+
# @yield [String] read data
|
363
|
+
# @return [IO] self
|
364
|
+
def read_loop(maxlen = 8192, &block)
|
365
|
+
Polyphony.backend_read_loop(self, maxlen, &block)
|
366
|
+
end
|
392
367
|
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
|
398
|
-
|
368
|
+
# Receives data from the io in an infinite loop, passing the data to the given
|
369
|
+
# receiver using the given method. If a block is given, the result of the
|
370
|
+
# method call to the receiver is passed to the block.
|
371
|
+
#
|
372
|
+
# This method can be used to feed data into parser objects. The following
|
373
|
+
# example shows how to feed data from a io directly into a MessagePack
|
374
|
+
# unpacker:
|
375
|
+
#
|
376
|
+
# unpacker = MessagePack::Unpacker.new
|
377
|
+
# io.feed_loop(unpacker, :feed_each) { |msg| handle_msg(msg) }
|
378
|
+
#
|
379
|
+
# @param receiver [any] receiver object
|
380
|
+
# @param method [Symbol] method to call
|
381
|
+
# @return [IO] self
|
382
|
+
def feed_loop(receiver, method = :call, &block)
|
383
|
+
Polyphony.backend_feed_loop(self, receiver, method, &block)
|
384
|
+
end
|
399
385
|
|
400
|
-
|
401
|
-
|
386
|
+
# Waits for the IO to become readable, with an optional timeout.
|
387
|
+
#
|
388
|
+
# @param timeout [Integer, nil] optional timeout in seconds.
|
389
|
+
# @return [IO] self
|
390
|
+
def wait_readable(timeout = nil)
|
391
|
+
return self if @read_buffer && !@read_buffer.empty?
|
392
|
+
|
393
|
+
if timeout
|
394
|
+
move_on_after(timeout) do
|
395
|
+
Polyphony.backend_wait_io(self, false)
|
396
|
+
self
|
397
|
+
end
|
398
|
+
else
|
402
399
|
Polyphony.backend_wait_io(self, false)
|
403
400
|
self
|
404
401
|
end
|
405
|
-
else
|
406
|
-
Polyphony.backend_wait_io(self, false)
|
407
|
-
self
|
408
402
|
end
|
409
|
-
end
|
410
403
|
|
411
|
-
# Waits for the IO to become writeable, with an optional timeout.
|
412
|
-
#
|
413
|
-
# @param timeout [Integer, nil] optional timeout in seconds.
|
414
|
-
# @return [IO] self
|
415
|
-
def wait_writable(timeout = nil)
|
416
|
-
|
417
|
-
|
404
|
+
# Waits for the IO to become writeable, with an optional timeout.
|
405
|
+
#
|
406
|
+
# @param timeout [Integer, nil] optional timeout in seconds.
|
407
|
+
# @return [IO] self
|
408
|
+
def wait_writable(timeout = nil)
|
409
|
+
if timeout
|
410
|
+
move_on_after(timeout) do
|
411
|
+
Polyphony.backend_wait_io(self, true)
|
412
|
+
self
|
413
|
+
end
|
414
|
+
else
|
418
415
|
Polyphony.backend_wait_io(self, true)
|
419
416
|
self
|
420
417
|
end
|
421
|
-
else
|
422
|
-
Polyphony.backend_wait_io(self, true)
|
423
|
-
self
|
424
418
|
end
|
425
|
-
end
|
426
|
-
|
427
|
-
# Splices data from the given IO. If maxlen is negative, splices repeatedly
|
428
|
-
# using absolute value of maxlen until EOF is encountered.
|
429
|
-
#
|
430
|
-
# @param src [IO, Polpyhony::Pipe] source to splice from
|
431
|
-
# @param maxlen [Integer] maximum bytes to splice
|
432
|
-
# @return [Integer] bytes spliced
|
433
|
-
def splice_from(src, maxlen)
|
434
|
-
Polyphony.backend_splice(src, self, maxlen)
|
435
|
-
end
|
436
419
|
|
437
|
-
|
438
|
-
#
|
420
|
+
# Splices data from the given IO. If maxlen is negative, splices repeatedly
|
421
|
+
# using absolute value of maxlen until EOF is encountered.
|
439
422
|
#
|
440
|
-
# @param src [IO, Polpyhony::Pipe] source to
|
441
|
-
# @param maxlen [Integer] maximum bytes to
|
442
|
-
# @return [Integer] bytes
|
443
|
-
def
|
444
|
-
Polyphony.
|
423
|
+
# @param src [IO, Polpyhony::Pipe] source to splice from
|
424
|
+
# @param maxlen [Integer] maximum bytes to splice
|
425
|
+
# @return [Integer] bytes spliced
|
426
|
+
def splice_from(src, maxlen)
|
427
|
+
Polyphony.backend_splice(src, self, maxlen)
|
428
|
+
end
|
429
|
+
|
430
|
+
if RUBY_PLATFORM =~ /linux/
|
431
|
+
# Tees data from the given IO.
|
432
|
+
#
|
433
|
+
# @param src [IO, Polpyhony::Pipe] source to tee from
|
434
|
+
# @param maxlen [Integer] maximum bytes to tee
|
435
|
+
# @return [Integer] bytes teed
|
436
|
+
def tee_from(src, maxlen)
|
437
|
+
Polyphony.backend_tee(src, self, maxlen)
|
438
|
+
end
|
445
439
|
end
|
446
|
-
end
|
447
440
|
end
|
@@ -2,6 +2,27 @@
|
|
2
2
|
|
3
3
|
require 'open3'
|
4
4
|
|
5
|
+
module Polyphony
|
6
|
+
# Intercepts calls to #trap
|
7
|
+
module TrapInterceptor
|
8
|
+
def trap(sig, command = nil, &block)
|
9
|
+
return super(sig, command) if command.is_a? String
|
10
|
+
|
11
|
+
block = command if !block && command.respond_to?(:call)
|
12
|
+
|
13
|
+
# The signal trap can be invoked at any time, including while the system
|
14
|
+
# backend is blocking while polling for events. In order to deal with this
|
15
|
+
# correctly, we run the signal handler code in an out-of-band, priority
|
16
|
+
# scheduled fiber, that will pass any uncaught exception (including
|
17
|
+
# SystemExit and Interrupt) to the main thread's main fiber. See also
|
18
|
+
# `Fiber#schedule_priority_oob_fiber`.
|
19
|
+
super(sig) do
|
20
|
+
Fiber.schedule_priority_oob_fiber(&block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
5
26
|
# Kernel extensions (methods available to all objects / call sites)
|
6
27
|
module ::Kernel
|
7
28
|
# @!visibility private
|
@@ -59,7 +80,7 @@ module ::Kernel
|
|
59
80
|
strs = args.inject([]) do |m, a|
|
60
81
|
m << a.inspect << "\n"
|
61
82
|
end
|
62
|
-
|
83
|
+
$stdout.write(*strs)
|
63
84
|
args.size == 1 ? args.first : args
|
64
85
|
end
|
65
86
|
|
@@ -72,6 +93,9 @@ module ::Kernel
|
|
72
93
|
end
|
73
94
|
|
74
95
|
class << self
|
96
|
+
# @!visibility private
|
97
|
+
alias_method :orig_trap, :trap
|
98
|
+
|
75
99
|
# @!visibility private
|
76
100
|
alias_method :orig_system, :system
|
77
101
|
|
@@ -92,23 +116,29 @@ module ::Kernel
|
|
92
116
|
# @!visibility private
|
93
117
|
alias_method :orig_trap, :trap
|
94
118
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
block = command if !block && command.respond_to?(:call)
|
100
|
-
|
101
|
-
# The signal trap can be invoked at any time, including while the system
|
102
|
-
# backend is blocking while polling for events. In order to deal with this
|
103
|
-
# correctly, we run the signal handler code in an out-of-band, priority
|
104
|
-
# scheduled fiber, that will pass any uncaught exception (including
|
105
|
-
# SystemExit and Interrupt) to the main thread's main fiber. See also
|
106
|
-
# `Fiber#schedule_priority_oob_fiber`.
|
107
|
-
orig_trap(sig) do
|
108
|
-
Fiber.schedule_priority_oob_fiber(&block)
|
109
|
-
end
|
119
|
+
prepend Polyphony::TrapInterceptor
|
120
|
+
|
121
|
+
class << self
|
122
|
+
prepend Polyphony::TrapInterceptor
|
110
123
|
end
|
111
124
|
|
125
|
+
# # @!visibility private
|
126
|
+
# def trap(sig, command = nil, &block)
|
127
|
+
# return orig_trap(sig, command) if command.is_a? String
|
128
|
+
|
129
|
+
# block = command if !block && command.respond_to?(:call)
|
130
|
+
|
131
|
+
# # The signal trap can be invoked at any time, including while the system
|
132
|
+
# # backend is blocking while polling for events. In order to deal with this
|
133
|
+
# # correctly, we run the signal handler code in an out-of-band, priority
|
134
|
+
# # scheduled fiber, that will pass any uncaught exception (including
|
135
|
+
# # SystemExit and Interrupt) to the main thread's main fiber. See also
|
136
|
+
# # `Fiber#schedule_priority_oob_fiber`.
|
137
|
+
# orig_trap(sig) do
|
138
|
+
# Fiber.schedule_priority_oob_fiber(&block)
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
|
112
142
|
private
|
113
143
|
|
114
144
|
# @!visibility private
|
@@ -116,3 +146,9 @@ module ::Kernel
|
|
116
146
|
src.read_loop { |data| dest << data }
|
117
147
|
end
|
118
148
|
end
|
149
|
+
|
150
|
+
module ::Process
|
151
|
+
class << self
|
152
|
+
prepend Polyphony::TrapInterceptor
|
153
|
+
end
|
154
|
+
end
|
@@ -84,7 +84,7 @@ class ::Object
|
|
84
84
|
def spin_loop(tag = nil, rate: nil, interval: nil, &block)
|
85
85
|
if rate || interval
|
86
86
|
Fiber.current.spin(tag, caller) do
|
87
|
-
throttled_loop(rate
|
87
|
+
throttled_loop(rate:, interval:, &block)
|
88
88
|
end
|
89
89
|
else
|
90
90
|
spin_loop_without_throttling(tag, caller, block)
|
@@ -200,8 +200,11 @@ class ::Object
|
|
200
200
|
# @param duration [Number, nil] duration
|
201
201
|
# @return [any]
|
202
202
|
def sleep(duration = nil)
|
203
|
-
duration
|
204
|
-
|
203
|
+
if duration
|
204
|
+
Polyphony.backend_sleep(duration)
|
205
|
+
else
|
206
|
+
Polyphony.backend_wait_event(true)
|
207
|
+
end
|
205
208
|
end
|
206
209
|
|
207
210
|
# Starts a throttled loop with the given rate. If `count:` is given, the
|
@@ -220,9 +223,7 @@ class ::Object
|
|
220
223
|
if opts[:count]
|
221
224
|
opts[:count].times { |_i| throttler.(&block) }
|
222
225
|
else
|
223
|
-
while true
|
224
|
-
throttler.(&block)
|
225
|
-
end
|
226
|
+
throttler.(&block) while true
|
226
227
|
end
|
227
228
|
rescue LocalJumpError, StopIteration
|
228
229
|
# break called or StopIteration raised
|
@@ -39,7 +39,7 @@ class ::OpenSSL::SSL::SSLSocket
|
|
39
39
|
|
40
40
|
# @!visibility private
|
41
41
|
def fill_rbuff
|
42
|
-
data =
|
42
|
+
data = sysread(BLOCK_SIZE)
|
43
43
|
if data
|
44
44
|
@rbuffer << data
|
45
45
|
else
|
@@ -103,15 +103,13 @@ class ::OpenSSL::SSL::SSLSocket
|
|
103
103
|
# @param buf [String, nil] buffer to read into
|
104
104
|
# @param buf_pos [Number] buffer position to read into
|
105
105
|
# @return [String] buffer used for reading
|
106
|
-
def read(maxlen = nil, buf = nil,
|
107
|
-
return readpartial(maxlen, buf,
|
106
|
+
def read(maxlen = nil, buf = nil, buffer_pos: 0)
|
107
|
+
return readpartial(maxlen, buf, buffer_pos:) if buf
|
108
108
|
|
109
109
|
buf = +''
|
110
110
|
return readpartial(maxlen, buf) if maxlen
|
111
111
|
|
112
|
-
while true
|
113
|
-
readpartial(4096, buf, -1)
|
114
|
-
end
|
112
|
+
readpartial(4096, buf, buffer_pos: -1) while true
|
115
113
|
rescue EOFError
|
116
114
|
buf
|
117
115
|
end
|
@@ -132,7 +130,7 @@ class ::OpenSSL::SSL::SSLSocket
|
|
132
130
|
# @param buf_pos [Number] buffer position to read into
|
133
131
|
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
134
132
|
# @return [String, nil] buffer used for reading or nil on `EOF`
|
135
|
-
def readpartial(maxlen, buf = +'',
|
133
|
+
def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
|
136
134
|
if buf_pos != 0
|
137
135
|
if (result = sysread(maxlen, +''))
|
138
136
|
if buf_pos == -1
|
@@ -265,7 +263,7 @@ class ::OpenSSL::SSL::SSLServer
|
|
265
263
|
# @param ignore_errors [boolean] whether to ignore IO and SSL errors
|
266
264
|
# @yield [OpenSSL::SSL::SSLSocket] accepted socket
|
267
265
|
# @return [OpenSSL::SSL::SSLServer] self
|
268
|
-
def accept_loop(ignore_errors
|
266
|
+
def accept_loop(ignore_errors: true)
|
269
267
|
loop do
|
270
268
|
yield accept
|
271
269
|
rescue OpenSSL::SSL::SSLError, SystemCallError => e
|
@@ -43,10 +43,8 @@ class Polyphony::Pipe
|
|
43
43
|
# @param buf [String, nil] buffer to read into
|
44
44
|
# @param buf_pos [Integer] buffer position to read into
|
45
45
|
# @return [String] read data
|
46
|
-
def read(len = nil, buf = nil,
|
47
|
-
if buf
|
48
|
-
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
49
|
-
end
|
46
|
+
def read(len = nil, buf = nil, buffer_pos: 0)
|
47
|
+
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
50
48
|
|
51
49
|
@read_buffer ||= +''
|
52
50
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
@@ -64,8 +62,8 @@ class Polyphony::Pipe
|
|
64
62
|
# @param buf_pos [Integer] buffer position to read into
|
65
63
|
# @param raise_on_eof [boolean] whether to raise an error if EOF is detected
|
66
64
|
# @return [String] read data
|
67
|
-
def readpartial(len, buf = +'',
|
68
|
-
result = Polyphony.backend_read(self, buf, len, false,
|
65
|
+
def readpartial(len, buf = +'', buffer_pos: 0, raise_on_eof: true)
|
66
|
+
result = Polyphony.backend_read(self, buf, len, false, buffer_pos)
|
69
67
|
raise EOFError if !result && raise_on_eof
|
70
68
|
|
71
69
|
result
|
@@ -106,7 +104,7 @@ class Polyphony::Pipe
|
|
106
104
|
idx = @read_buffer.index(sep)
|
107
105
|
return @read_buffer.slice!(0, idx + sep_size) if idx
|
108
106
|
|
109
|
-
result = readpartial(8192, @read_buffer, -1)
|
107
|
+
result = readpartial(8192, @read_buffer, buffer_pos: -1)
|
110
108
|
return nil unless result
|
111
109
|
end
|
112
110
|
rescue EOFError
|
@@ -26,9 +26,8 @@ end
|
|
26
26
|
|
27
27
|
# Socket extensions # TODO: rewrite in C
|
28
28
|
class ::Socket < ::BasicSocket
|
29
|
-
|
30
29
|
# Accepts an incoming connection.
|
31
|
-
|
30
|
+
#
|
32
31
|
# @return [TCPSocket] new connection
|
33
32
|
def accept
|
34
33
|
Polyphony.backend_accept(self, TCPSocket)
|
@@ -73,12 +72,9 @@ class ::Socket < ::BasicSocket
|
|
73
72
|
# @param buf [String, nil] buffer to read into
|
74
73
|
# @param buf_pos [Number] buffer position to read into
|
75
74
|
# @return [String] buffer used for reading
|
76
|
-
def read(len = nil, buf = nil,
|
75
|
+
def read(len = nil, buf = nil, buffer_pos: 0)
|
77
76
|
return '' if len == 0
|
78
|
-
|
79
|
-
if buf
|
80
|
-
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
81
|
-
end
|
77
|
+
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
82
78
|
|
83
79
|
@read_buffer ||= +''
|
84
80
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
@@ -167,8 +163,8 @@ class ::Socket < ::BasicSocket
|
|
167
163
|
# @param buf_pos [Number] buffer position to read into
|
168
164
|
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
169
165
|
# @return [String, nil] buffer used for reading or nil on `EOF`
|
170
|
-
def readpartial(maxlen, buf = +'',
|
171
|
-
result = Polyphony.backend_recv(self, buf, maxlen,
|
166
|
+
def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
|
167
|
+
result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
|
172
168
|
raise EOFError if !result && raise_on_eof
|
173
169
|
|
174
170
|
result
|
@@ -210,8 +206,8 @@ class ::Socket < ::BasicSocket
|
|
210
206
|
end
|
211
207
|
|
212
208
|
class << self
|
213
|
-
|
214
|
-
|
209
|
+
# @!visibility private
|
210
|
+
alias_method :orig_getaddrinfo, :getaddrinfo
|
215
211
|
|
216
212
|
# Resolves the given addr using a worker thread from the default thread
|
217
213
|
# pool.
|
@@ -337,12 +333,9 @@ class ::TCPSocket < ::IPSocket
|
|
337
333
|
# @param buf [String, nil] buffer to read into
|
338
334
|
# @param buf_pos [Number] buffer position to read into
|
339
335
|
# @return [String] buffer used for reading
|
340
|
-
def read(len = nil, buf = nil,
|
336
|
+
def read(len = nil, buf = nil, buffer_pos: 0)
|
341
337
|
return '' if len == 0
|
342
|
-
|
343
|
-
if buf
|
344
|
-
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
345
|
-
end
|
338
|
+
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
346
339
|
|
347
340
|
@read_buffer ||= +''
|
348
341
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
@@ -413,9 +406,10 @@ class ::TCPSocket < ::IPSocket
|
|
413
406
|
# @param buf_pos [Number] buffer position to read into
|
414
407
|
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
415
408
|
# @return [String, nil] buffer used for reading or nil on `EOF`
|
416
|
-
def readpartial(maxlen, buf = +'',
|
417
|
-
result = Polyphony.backend_recv(self, buf, maxlen,
|
409
|
+
def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
|
410
|
+
result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
|
418
411
|
raise EOFError if !result && raise_on_eof
|
412
|
+
|
419
413
|
result
|
420
414
|
end
|
421
415
|
|
@@ -430,7 +424,7 @@ class ::TCPSocket < ::IPSocket
|
|
430
424
|
# @param exception [bool] whether to raise an exception if not ready for reading
|
431
425
|
# @return [String, :wait_readable] read buffer
|
432
426
|
def read_nonblock(maxlen, buf = nil, exception: true)
|
433
|
-
@io.read_nonblock(maxlen, buf, exception:
|
427
|
+
@io.read_nonblock(maxlen, buf, exception:)
|
434
428
|
end
|
435
429
|
|
436
430
|
# Performs a non-blocking to the socket. If the socket is not ready for
|
@@ -442,13 +436,12 @@ class ::TCPSocket < ::IPSocket
|
|
442
436
|
# @param exception [bool] whether to raise an exception if not ready for reading
|
443
437
|
# @return [Integer, :wait_readable] number of bytes written
|
444
438
|
def write_nonblock(buf, exception: true)
|
445
|
-
@io.write_nonblock(buf, exception:
|
439
|
+
@io.write_nonblock(buf, exception:)
|
446
440
|
end
|
447
441
|
end
|
448
442
|
|
449
443
|
# TCPServer extensions
|
450
444
|
class ::TCPServer < ::TCPSocket
|
451
|
-
|
452
445
|
# Initializes the TCP server socket.
|
453
446
|
#
|
454
447
|
# @param hostname [String, nil] hostname to connect to
|
@@ -546,12 +539,9 @@ class ::UNIXSocket < ::BasicSocket
|
|
546
539
|
# @param buf [String, nil] buffer to read into
|
547
540
|
# @param buf_pos [Number] buffer position to read into
|
548
541
|
# @return [String] buffer used for reading
|
549
|
-
def read(len = nil, buf = nil,
|
542
|
+
def read(len = nil, buf = nil, buffer_pos: 0)
|
550
543
|
return '' if len == 0
|
551
|
-
|
552
|
-
if buf
|
553
|
-
return Polyphony.backend_read(self, buf, len, true, buf_pos)
|
554
|
-
end
|
544
|
+
return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
|
555
545
|
|
556
546
|
@read_buffer ||= +''
|
557
547
|
result = Polyphony.backend_read(self, @read_buffer, len, true, -1)
|
@@ -648,9 +638,10 @@ class ::UNIXSocket < ::BasicSocket
|
|
648
638
|
# @param buf_pos [Number] buffer position to read into
|
649
639
|
# @param raise_on_eof [bool] whether to raise an exception on `EOF`
|
650
640
|
# @return [String, nil] buffer used for reading or nil on `EOF`
|
651
|
-
def readpartial(maxlen, buf = +'',
|
652
|
-
result = Polyphony.backend_recv(self, buf, maxlen,
|
641
|
+
def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
|
642
|
+
result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
|
653
643
|
raise EOFError if !result && raise_on_eof
|
644
|
+
|
654
645
|
result
|
655
646
|
end
|
656
647
|
|
@@ -665,7 +656,7 @@ class ::UNIXSocket < ::BasicSocket
|
|
665
656
|
# @param exception [bool] whether to raise an exception if not ready for reading
|
666
657
|
# @return [String, :wait_readable] read buffer
|
667
658
|
def read_nonblock(maxlen, buf = nil, exception: true)
|
668
|
-
@io.read_nonblock(maxlen, buf, exception:
|
659
|
+
@io.read_nonblock(maxlen, buf, exception:)
|
669
660
|
end
|
670
661
|
|
671
662
|
# Performs a non-blocking to the socket. If the socket is not ready for
|
@@ -677,7 +668,7 @@ class ::UNIXSocket < ::BasicSocket
|
|
677
668
|
# @param exception [bool] whether to raise an exception if not ready for reading
|
678
669
|
# @return [Integer, :wait_readable] number of bytes written
|
679
670
|
def write_nonblock(buf, exception: true)
|
680
|
-
@io.write_nonblock(buf, exception:
|
671
|
+
@io.write_nonblock(buf, exception:)
|
681
672
|
end
|
682
673
|
end
|
683
674
|
|
@@ -724,13 +715,13 @@ class ::UDPSocket < ::IPSocket
|
|
724
715
|
# @return [Integer] bytes sent
|
725
716
|
def send(msg, flags, *addr)
|
726
717
|
sockaddr = case addr.size
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
718
|
+
when 2
|
719
|
+
Socket.sockaddr_in(addr[1], addr[0])
|
720
|
+
when 1
|
721
|
+
addr[0]
|
722
|
+
else
|
723
|
+
nil
|
724
|
+
end
|
734
725
|
|
735
726
|
Polyphony.backend_sendmsg(self, msg, flags, sockaddr, nil)
|
736
727
|
end
|
@@ -81,7 +81,6 @@ class ::Thread
|
|
81
81
|
return self if @terminated
|
82
82
|
|
83
83
|
raise Polyphony::Terminate
|
84
|
-
self
|
85
84
|
end
|
86
85
|
|
87
86
|
# @!visibility private
|
@@ -160,9 +159,8 @@ class ::Thread
|
|
160
159
|
#
|
161
160
|
# @param result [any] thread's return value
|
162
161
|
def finalize(result)
|
163
|
-
|
164
|
-
|
165
|
-
end
|
162
|
+
Fiber.current.shutdown_all_children if !Fiber.current.children.empty?
|
163
|
+
|
166
164
|
@finalization_mutex.synchronize do
|
167
165
|
@terminated = true
|
168
166
|
@result = result
|
@@ -4,7 +4,6 @@ require 'timeout'
|
|
4
4
|
|
5
5
|
# Timeout extensions
|
6
6
|
module ::Timeout
|
7
|
-
|
8
7
|
# Sets a timeout for the given block. This method provides an equivalent API
|
9
8
|
# to the stock Timeout API provided by Ruby. In case of a timeout, the block
|
10
9
|
# will be interrupted and an exception will be raised according to the given
|
data/lib/polyphony/version.rb
CHANGED