polyphony 1.1 → 1.2
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/.github/workflows/test_io_uring.yml +1 -1
- data/.rubocop.yml +16 -8
- data/CHANGELOG.md +13 -0
- data/README.md +2 -1
- data/docs/advanced-io.md +141 -44
- 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 +2 -2
- 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 +6 -4
@@ -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