polyphony 1.3 → 1.5

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.
@@ -59,7 +59,7 @@ class ::Socket < ::BasicSocket
59
59
 
60
60
  # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
61
61
  # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
62
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
62
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
63
63
  # given, reads into the given offset (in bytes) in the given buffer. If the
64
64
  # given buffer offset is negative, it is calculated from the current end of
65
65
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -70,9 +70,9 @@ class ::Socket < ::BasicSocket
70
70
  #
71
71
  # @param len [Integer, nil] maximum bytes to read from socket
72
72
  # @param buf [String, nil] buffer to read into
73
- # @param buf_pos [Number] buffer position to read into
73
+ # @param buffer_pos [Number] buffer position to read into
74
74
  # @return [String] buffer used for reading
75
- def read(len = nil, buf = nil, buffer_pos: 0)
75
+ def read(len = nil, buf = nil, buffer_pos = 0)
76
76
  return '' if len == 0
77
77
  return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
78
78
 
@@ -148,7 +148,7 @@ class ::Socket < ::BasicSocket
148
148
  end
149
149
 
150
150
  # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
151
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
151
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
152
152
  # given, reads into the given offset (in bytes) in the given buffer. If the
153
153
  # given buffer offset is negative, it is calculated from the current end of
154
154
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -160,10 +160,10 @@ class ::Socket < ::BasicSocket
160
160
  #
161
161
  # @param maxlen [Integer, nil] maximum bytes to read from socket
162
162
  # @param buf [String, nil] buffer to read into
163
- # @param buf_pos [Number] buffer position to read into
163
+ # @param buffer_pos [Number] buffer position to read into
164
164
  # @param raise_on_eof [bool] whether to raise an exception on `EOF`
165
165
  # @return [String, nil] buffer used for reading or nil on `EOF`
166
- def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
166
+ def readpartial(maxlen, buf = +'', buffer_pos = 0, raise_on_eof = true)
167
167
  result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
168
168
  raise EOFError if !result && raise_on_eof
169
169
 
@@ -320,7 +320,7 @@ class ::TCPSocket < ::IPSocket
320
320
 
321
321
  # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
322
322
  # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
323
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
323
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
324
324
  # given, reads into the given offset (in bytes) in the given buffer. If the
325
325
  # given buffer offset is negative, it is calculated from the current end of
326
326
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -331,9 +331,9 @@ class ::TCPSocket < ::IPSocket
331
331
  #
332
332
  # @param len [Integer, nil] maximum bytes to read from socket
333
333
  # @param buf [String, nil] buffer to read into
334
- # @param buf_pos [Number] buffer position to read into
334
+ # @param buffer_pos [Number] buffer position to read into
335
335
  # @return [String] buffer used for reading
336
- def read(len = nil, buf = nil, buffer_pos: 0)
336
+ def read(len = nil, buf = nil, buffer_pos = 0)
337
337
  return '' if len == 0
338
338
  return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
339
339
 
@@ -391,7 +391,7 @@ class ::TCPSocket < ::IPSocket
391
391
  end
392
392
 
393
393
  # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
394
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
394
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
395
395
  # given, reads into the given offset (in bytes) in the given buffer. If the
396
396
  # given buffer offset is negative, it is calculated from the current end of
397
397
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -403,10 +403,10 @@ class ::TCPSocket < ::IPSocket
403
403
  #
404
404
  # @param maxlen [Integer, nil] maximum bytes to read from socket
405
405
  # @param buf [String, nil] buffer to read into
406
- # @param buf_pos [Number] buffer position to read into
406
+ # @param buffer_pos [Number] buffer position to read into
407
407
  # @param raise_on_eof [bool] whether to raise an exception on `EOF`
408
408
  # @return [String, nil] buffer used for reading or nil on `EOF`
409
- def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
409
+ def readpartial(maxlen, buf = +'', buffer_pos = 0, raise_on_eof = true)
410
410
  result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
411
411
  raise EOFError if !result && raise_on_eof
412
412
 
@@ -464,20 +464,6 @@ class ::TCPServer < ::TCPSocket
464
464
  Polyphony.backend_accept(@io, TCPSocket)
465
465
  end
466
466
 
467
- if Polyphony.instance_methods(false).include?(:backend_multishot_accept)
468
- # Starts a multishot accept operation (only available with io_uring
469
- # backend). Example usage:
470
- #
471
- # server.multishot_accept do
472
- # server.accept_loop { |c| handle_connection(c) }
473
- # end
474
- #
475
- # @return [any] return value of code block
476
- def multishot_accept(&block)
477
- Polyphony.backend_multishot_accept(@io, &block)
478
- end
479
- end
480
-
481
467
  # Accepts incoming connections in an infinite loop.
482
468
  #
483
469
  # @yield [TCPSocket] accepted socket
@@ -526,7 +512,7 @@ class ::UNIXSocket < ::BasicSocket
526
512
 
527
513
  # Reads from the socket. If `maxlen` is given, reads up to `maxlen` bytes from
528
514
  # the socket, otherwise reads to `EOF`. If `buf` is given, it is used as the
529
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
515
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
530
516
  # given, reads into the given offset (in bytes) in the given buffer. If the
531
517
  # given buffer offset is negative, it is calculated from the current end of
532
518
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -537,9 +523,9 @@ class ::UNIXSocket < ::BasicSocket
537
523
  #
538
524
  # @param len [Integer, nil] maximum bytes to read from socket
539
525
  # @param buf [String, nil] buffer to read into
540
- # @param buf_pos [Number] buffer position to read into
526
+ # @param buffer_pos [Number] buffer position to read into
541
527
  # @return [String] buffer used for reading
542
- def read(len = nil, buf = nil, buffer_pos: 0)
528
+ def read(len = nil, buf = nil, buffer_pos = 0)
543
529
  return '' if len == 0
544
530
  return Polyphony.backend_read(self, buf, len, true, buffer_pos) if buf
545
531
 
@@ -623,7 +609,7 @@ class ::UNIXSocket < ::BasicSocket
623
609
  end
624
610
 
625
611
  # Reads up to `maxlen` from the socket. If `buf` is given, it is used as the
626
- # buffer to read into, otherwise a new string is allocated. If `buf_pos` is
612
+ # buffer to read into, otherwise a new string is allocated. If `buffer_pos` is
627
613
  # given, reads into the given offset (in bytes) in the given buffer. If the
628
614
  # given buffer offset is negative, it is calculated from the current end of
629
615
  # the buffer (`-1` means the read data will be appended to the end of the
@@ -635,10 +621,10 @@ class ::UNIXSocket < ::BasicSocket
635
621
  #
636
622
  # @param maxlen [Integer, nil] maximum bytes to read from socket
637
623
  # @param buf [String, nil] buffer to read into
638
- # @param buf_pos [Number] buffer position to read into
624
+ # @param buffer_pos [Number] buffer position to read into
639
625
  # @param raise_on_eof [bool] whether to raise an exception on `EOF`
640
626
  # @return [String, nil] buffer used for reading or nil on `EOF`
641
- def readpartial(maxlen, buf = +'', buffer_pos: 0, raise_on_eof: true)
627
+ def readpartial(maxlen, buf = +'', buffer_pos = 0, raise_on_eof = true)
642
628
  result = Polyphony.backend_recv(self, buf, maxlen, buffer_pos)
643
629
  raise EOFError if !result && raise_on_eof
644
630
 
@@ -14,6 +14,10 @@ module ::Timeout
14
14
  # @param message [String] exception message
15
15
  # @return [any] block's return value
16
16
  def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
17
- cancel_after(sec, with_exception: [klass, message], &block)
17
+ if sec.nil? || sec == 0
18
+ block.call
19
+ else
20
+ cancel_after(sec, with_exception: [klass, message], &block)
21
+ end
18
22
  end
19
23
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Polyphony
4
4
  # @!visibility private
5
- VERSION = '1.3'
5
+ VERSION = '1.5'
6
6
  end
data/test/stress.rb CHANGED
@@ -3,11 +3,16 @@
3
3
  count = ARGV[0] ? ARGV[0].to_i : 100
4
4
  test_name = ARGV[1]
5
5
 
6
- $test_cmd = +'ruby test/test_scenarios.rb'
6
+ $test_cmd = +'ruby test/run.rb'
7
7
  if test_name
8
8
  $test_cmd << " --name #{test_name}"
9
9
  end
10
10
 
11
+ puts '*' * 40
12
+ puts
13
+ puts $test_cmd
14
+ puts
15
+
11
16
  def run_test(count)
12
17
  puts "#{count}: running tests..."
13
18
  # sleep 1
data/test/test_backend.rb CHANGED
@@ -317,6 +317,8 @@ class BackendTest < MiniTest::Test
317
317
  end
318
318
 
319
319
  def test_splice_chunks
320
+ skip if !Thread.current.backend.respond_to?(:splice_chunks)
321
+
320
322
  body = 'abcd' * 4
321
323
  chunk_size = 12
322
324
 
@@ -346,8 +348,8 @@ class BackendTest < MiniTest::Test
346
348
  expected = "Content-Type: foo\r\n\r\n#{12.to_s(16)}\r\n#{body[0..11]}\r\n#{4.to_s(16)}\r\n#{body[12..15]}\r\n0\r\n\r\n"
347
349
  assert_equal expected, buf
348
350
  ensure
349
- o.close
350
- w.close
351
+ o&.close
352
+ w&.close
351
353
  end
352
354
 
353
355
  def test_idle_gc
@@ -544,4 +546,11 @@ class BackendChainTest < MiniTest::Test
544
546
  # released properly before raising the error (for the time being this has
545
547
  # been verified manually).
546
548
  end
549
+
550
+ def test_backend_close
551
+ r, w = IO.pipe
552
+ w << 'abc'
553
+ Thread.backend.close(w)
554
+ assert w.closed?
555
+ end
547
556
  end
data/test/test_ext.rb CHANGED
@@ -242,6 +242,20 @@ class TimeoutTest < MiniTest::Test
242
242
  assert_equal [0, 1, 2], buffer
243
243
  end
244
244
 
245
+ def test_timeout_with_nil_or_zero
246
+ v = Timeout.timeout(nil) do
247
+ sleep 0.01
248
+ :foo
249
+ end
250
+ assert_equal :foo, v
251
+
252
+ v = Timeout.timeout(0) do
253
+ sleep 0.01
254
+ :bar
255
+ end
256
+ assert_equal :bar, v
257
+ end
258
+
245
259
  class MyTimeout < Exception
246
260
  end
247
261
 
@@ -128,16 +128,16 @@ class MoveOnAfterTest < MiniTest::Test
128
128
 
129
129
  def test_move_on_after_with_reset
130
130
  t0 = monotonic_clock
131
- v = move_on_after(0.01, with_value: :moved_on) do |timeout|
132
- sleep 0.006
131
+ v = move_on_after(0.1, with_value: :moved_on) do |timeout|
132
+ sleep 0.06
133
133
  timeout.reset
134
- sleep 0.006
134
+ sleep 0.06
135
135
  nil
136
136
  end
137
137
  t1 = monotonic_clock
138
138
 
139
139
  assert_nil v
140
- assert_in_range 0.012..0.025, t1 - t0 if IS_LINUX
140
+ assert_in_range 0.12..0.30, t1 - t0 if IS_LINUX
141
141
  end
142
142
 
143
143
  def test_nested_move_on_after
@@ -161,7 +161,7 @@ class MoveOnAfterTest < MiniTest::Test
161
161
  end
162
162
  t1 = monotonic_clock
163
163
  assert_equal 2, o
164
- assert_in_range 0.008..0.025, t1 - t0 if IS_LINUX
164
+ assert_in_range 0.008..0.035, t1 - t0 if IS_LINUX
165
165
  end
166
166
  end
167
167
 
data/test/test_io.rb CHANGED
@@ -89,7 +89,7 @@ class IOTest < MiniTest::Test
89
89
 
90
90
  buf = +'def'
91
91
  o << 'foobar'
92
- assert_equal 'deffoobar', i.read(6, buf, buffer_pos: -1)
92
+ assert_equal 'deffoobar', i.read(6, buf, -1)
93
93
  assert_equal 'deffoobar', buf
94
94
  end
95
95
 
data/test/test_signal.rb CHANGED
@@ -4,6 +4,10 @@ require_relative 'helper'
4
4
 
5
5
  class SignalTrapTest < Minitest::Test
6
6
  def test_signal_handler_trace
7
+ if Thread.current.backend.kind != :io_uring
8
+ skip "Skipping signal handler trace because Backend_close on libev behaves differently"
9
+ end
10
+
7
11
  i1, o1 = IO.pipe
8
12
  i2, o2 = IO.pipe
9
13
  pid = Process.pid
@@ -39,16 +43,21 @@ class SignalTrapTest < Minitest::Test
39
43
  end
40
44
 
41
45
  expected = [
42
- [:block, :main],
46
+ [:block, :main],
47
+ [:enter_poll, :main],
48
+ [:schedule, :main],
49
+ [:leave_poll, :main],
50
+ [:unblock, :main],
51
+ [:block, :main],
43
52
  [:enter_poll, :main],
44
53
  [:leave_poll, :main],
45
- [:unblock, :oob],
46
- [:terminate, :oob],
47
- [:block, :oob],
54
+ [:unblock, :oob],
55
+ [:terminate, :oob],
56
+ [:block, :oob],
48
57
  [:enter_poll, :oob],
49
- [:schedule, :main],
58
+ [:schedule, :main],
50
59
  [:leave_poll, :oob],
51
- [:unblock, :main]
60
+ [:unblock, :main]
52
61
  ]
53
62
  if Thread.backend.kind == :libev
54
63
  expected += [
data/test/test_socket.rb CHANGED
@@ -73,12 +73,8 @@ class TCPSocketTest < MiniTest::Test
73
73
  def test_read
74
74
  port, server = start_tcp_server_on_random_port
75
75
  server_fiber = spin do
76
- while (socket = server.accept)
77
- spin do
78
- while (data = socket.readpartial(8192))
79
- socket << data
80
- end
81
- end
76
+ server.accept_loop do |socket|
77
+ spin { socket.recv_loop { |data| socket << data } }
82
78
  end
83
79
  end
84
80
 
@@ -98,7 +94,7 @@ class TCPSocketTest < MiniTest::Test
98
94
 
99
95
  buf = +'def'
100
96
  client << 'foobar'
101
- assert_equal 'deffoobar', client.read(6, buf, buffer_pos: -1)
97
+ assert_equal 'deffoobar', client.read(6, buf, -1)
102
98
  assert_equal 'deffoobar', buf
103
99
 
104
100
  client.close
@@ -394,98 +390,3 @@ class SSLSocketTest < MiniTest::Test
394
390
  assert_kind_of OpenSSL::SSL::SSLError, errors.first
395
391
  end
396
392
  end
397
-
398
- class MultishotAcceptTest < MiniTest::Test
399
- def setup
400
- skip if !TCPServer.instance_methods(false).include?(:multishot_accept)
401
- end
402
-
403
- def start_tcp_server_on_random_port(host = '127.0.0.1')
404
- port = rand(1100..60000)
405
- server = TCPServer.new(host, port)
406
- [port, server]
407
- rescue Errno::EADDRINUSE
408
- retry
409
- end
410
-
411
- def test_multishot_accept_while_loop
412
- port, server = start_tcp_server_on_random_port
413
- server_fiber = spin do
414
- server.multishot_accept do
415
- while (socket = server.accept)
416
- spin do
417
- while (data = socket.gets(8192))
418
- socket << data
419
- end
420
- end
421
- end
422
- end
423
- end
424
-
425
- snooze
426
- client = TCPSocket.new('127.0.0.1', port)
427
- client.write("1234\n")
428
- assert_equal "1234\n", client.recv(8192)
429
- client.close
430
-
431
- client = TCPSocket.new('127.0.0.1', port)
432
- client.write("5678\n")
433
- assert_equal "5678\n", client.recv(8192)
434
- client.close
435
-
436
- ensure
437
- server_fiber&.stop
438
- server_fiber&.await
439
- server&.close
440
- end
441
-
442
- def spin_client(socket)
443
- spin do
444
- while (data = socket.gets(8192))
445
- socket << data
446
- end
447
- end
448
- end
449
-
450
- def test_multishot_accept_loop
451
- port, server = start_tcp_server_on_random_port
452
- server_fiber = spin do
453
- server.multishot_accept do
454
- server.accept_loop { |s| spin_client(s) }
455
- end
456
- end
457
-
458
- snooze
459
- client = TCPSocket.new('127.0.0.1', port)
460
- client.write("1234\n")
461
- assert_equal "1234\n", client.recv(8192)
462
- client.close
463
-
464
- client = TCPSocket.new('127.0.0.1', port)
465
- client.write("5678\n")
466
- assert_equal "5678\n", client.recv(8192)
467
- client.close
468
-
469
- ensure
470
- server_fiber&.stop
471
- server_fiber&.await
472
- server&.close
473
- end
474
-
475
- def test_multishot_accept_error
476
- port, server = start_tcp_server_on_random_port
477
- error = nil
478
- server_fiber = spin do
479
- server.multishot_accept do
480
- server.accept_loop { |s| spin_client(s) }
481
- rescue SystemCallError => e
482
- error = e
483
- end
484
- end
485
- snooze
486
- server.close
487
- snooze
488
- server_fiber.await
489
- assert_kind_of Errno::EBADF, error
490
- end
491
- end
data/test/test_timer.rb CHANGED
@@ -73,7 +73,7 @@ class TimerCancelAfterTest < MiniTest::Test
73
73
  end
74
74
  end
75
75
  t1 = Time.now
76
- assert_in_range 0.01..0.03, t1 - t0 if IS_LINUX
76
+ assert_in_range 0.01..0.04, t1 - t0 if IS_LINUX
77
77
  end
78
78
 
79
79
  def test_timer_cancel_after_with_reset
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polyphony
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.3'
4
+ version: '1.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-23 00:00:00.000000000 Z
11
+ date: 2023-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -150,7 +150,7 @@ dependencies:
150
150
  - - '='
151
151
  - !ruby/object:Gem::Version
152
152
  version: 2.10.0
153
- description:
153
+ description:
154
154
  email: sharon@noteflakes.com
155
155
  executables: []
156
156
  extensions:
@@ -191,6 +191,7 @@ files:
191
191
  - docs/extending.md
192
192
  - docs/faq.md
193
193
  - docs/fiber-scheduling.md
194
+ - docs/installation.md
194
195
  - docs/overview.md
195
196
  - docs/readme.md
196
197
  - docs/tutorial.md
@@ -234,6 +235,7 @@ files:
234
235
  - examples/core/shutdown_all_children.rb
235
236
  - examples/core/spin.rb
236
237
  - examples/core/spin_error_backtrace.rb
238
+ - examples/core/stages.rb
237
239
  - examples/core/stream_mockup.rb
238
240
  - examples/core/supervise-process.rb
239
241
  - examples/core/supervisor.rb
@@ -310,6 +312,7 @@ files:
310
312
  - examples/pipes/gzip.rb
311
313
  - examples/pipes/gzip_http_server.rb
312
314
  - examples/pipes/http_server.rb
315
+ - examples/pipes/http_server2.rb
313
316
  - examples/pipes/tcp_proxy.rb
314
317
  - examples/pipes/tee.rb
315
318
  - ext/libev/Changes
@@ -354,6 +357,7 @@ files:
354
357
  - ext/polyphony/runqueue_ring_buffer.h
355
358
  - ext/polyphony/socket_extensions.c
356
359
  - ext/polyphony/thread.c
360
+ - ext/polyphony/win_uio.h
357
361
  - ext/polyphony/zlib_conf.rb
358
362
  - ext/test_eintr.c
359
363
  - lib/polyphony.rb
@@ -656,7 +660,7 @@ metadata:
656
660
  source_code_uri: https://github.com/digital-fabric/polyphony
657
661
  documentation_uri: https://www.rubydoc.info/gems/polyphony
658
662
  changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
659
- post_install_message:
663
+ post_install_message:
660
664
  rdoc_options:
661
665
  - "--title"
662
666
  - polyphony
@@ -676,7 +680,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
676
680
  version: '0'
677
681
  requirements: []
678
682
  rubygems_version: 3.4.1
679
- signing_key:
683
+ signing_key:
680
684
  specification_version: 4
681
685
  summary: Fine grained concurrency for Ruby
682
686
  test_files: []