polyphony 0.72 → 0.75

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +15 -11
  3. data/.github/workflows/test_io_uring.yml +32 -0
  4. data/.gitignore +3 -1
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile.lock +16 -13
  7. data/bin/pdbg +0 -0
  8. data/bin/polyphony-debug +0 -0
  9. data/bin/stress.rb +0 -0
  10. data/bin/test +0 -0
  11. data/docs/api-reference/exception.md +5 -1
  12. data/examples/core/ring.rb +29 -0
  13. data/ext/polyphony/backend_common.c +90 -12
  14. data/ext/polyphony/backend_common.h +9 -1
  15. data/ext/polyphony/backend_io_uring.c +257 -134
  16. data/ext/polyphony/backend_io_uring_context.c +1 -0
  17. data/ext/polyphony/backend_io_uring_context.h +2 -1
  18. data/ext/polyphony/backend_libev.c +33 -29
  19. data/ext/polyphony/event.c +5 -2
  20. data/ext/polyphony/extconf.rb +1 -0
  21. data/ext/polyphony/polyphony.c +11 -1
  22. data/ext/polyphony/polyphony.h +9 -2
  23. data/ext/polyphony/queue.c +10 -5
  24. data/ext/polyphony/runqueue_ring_buffer.c +3 -1
  25. data/ext/polyphony/socket_extensions.c +5 -2
  26. data/ext/polyphony/thread.c +1 -1
  27. data/lib/polyphony/{extensions → core}/debug.rb +0 -0
  28. data/lib/polyphony/core/global_api.rb +0 -3
  29. data/lib/polyphony/extensions/exception.rb +45 -0
  30. data/lib/polyphony/extensions/fiber.rb +85 -4
  31. data/lib/polyphony/extensions/{core.rb → kernel.rb} +0 -73
  32. data/lib/polyphony/extensions/openssl.rb +5 -1
  33. data/lib/polyphony/extensions/process.rb +19 -0
  34. data/lib/polyphony/extensions/socket.rb +12 -6
  35. data/lib/polyphony/extensions/thread.rb +9 -3
  36. data/lib/polyphony/extensions/timeout.rb +10 -0
  37. data/lib/polyphony/extensions.rb +9 -0
  38. data/lib/polyphony/version.rb +1 -1
  39. data/lib/polyphony.rb +4 -4
  40. data/test/helper.rb +0 -5
  41. data/test/test_backend.rb +3 -5
  42. data/test/test_global_api.rb +21 -12
  43. data/test/test_io.rb +2 -2
  44. data/test/test_kernel.rb +2 -2
  45. data/test/test_process_supervision.rb +1 -1
  46. data/test/test_signal.rb +20 -1
  47. data/test/test_socket.rb +35 -2
  48. data/test/test_thread.rb +1 -1
  49. data/test/test_thread_pool.rb +1 -1
  50. data/test/test_throttler.rb +3 -3
  51. data/test/test_timer.rb +1 -1
  52. data/test/test_trace.rb +7 -1
  53. metadata +11 -5
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Overrides for Process
4
+ module ::Process
5
+ class << self
6
+ alias_method :orig_detach, :detach
7
+ def detach(pid)
8
+ fiber = spin { Polyphony.backend_waitpid(pid) }
9
+ fiber.define_singleton_method(:pid) { pid }
10
+ fiber
11
+ end
12
+
13
+ alias_method :orig_daemon, :daemon
14
+ def daemon(*args)
15
+ orig_daemon(*args)
16
+ Polyphony.original_pid = Process.pid
17
+ end
18
+ end
19
+ end
@@ -31,7 +31,7 @@ class ::Socket
31
31
  alias_method :orig_read, :read
32
32
  def read(maxlen = nil, buf = nil, buf_pos = 0)
33
33
  return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
34
- return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
34
+ return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
35
35
 
36
36
  buf = +''
37
37
  len = buf.bytesize
@@ -120,8 +120,13 @@ class ::TCPSocket
120
120
 
121
121
  attr_reader :io
122
122
 
123
+ def self.open(*args)
124
+ new(*args)
125
+ end
126
+
123
127
  def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
124
- @io = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
128
+ remote_addr = Addrinfo.tcp(remote_host, remote_port)
129
+ @io = Socket.new remote_addr.afamily, Socket::SOCK_STREAM
125
130
  if local_host && local_port
126
131
  addr = Addrinfo.tcp(local_host, local_port)
127
132
  @io.bind(addr)
@@ -167,7 +172,7 @@ class ::TCPSocket
167
172
  alias_method :orig_read, :read
168
173
  def read(maxlen = nil, buf = nil, buf_pos = 0)
169
174
  return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
170
- return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
175
+ return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
171
176
 
172
177
  buf = +''
173
178
  len = buf.bytesize
@@ -224,8 +229,9 @@ end
224
229
  # Override stock TCPServer code by encapsulating a Socket instance.
225
230
  class ::TCPServer
226
231
  def initialize(hostname = nil, port = 0)
227
- @io = Socket.new Socket::AF_INET, Socket::SOCK_STREAM
228
- @io.bind(Addrinfo.tcp(hostname, port))
232
+ addr = Addrinfo.tcp(hostname, port)
233
+ @io = Socket.new addr.afamily, Socket::SOCK_STREAM
234
+ @io.bind(addr)
229
235
  @io.listen(0)
230
236
  end
231
237
 
@@ -259,7 +265,7 @@ class ::UNIXSocket
259
265
  alias_method :orig_read, :read
260
266
  def read(maxlen = nil, buf = nil, buf_pos = 0)
261
267
  return Polyphony.backend_recv(self, buf, maxlen, buf_pos) if buf
262
- return Polyphony.backend_recv(self, buf || +'', maxlen, 0) if maxlen
268
+ return Polyphony.backend_recv(self, +'', maxlen, 0) if maxlen
263
269
 
264
270
  buf = +''
265
271
  len = buf.bytesize
@@ -18,14 +18,20 @@ class ::Thread
18
18
  def execute
19
19
  # backend must be created in the context of the new thread, therefore it
20
20
  # cannot be created in Thread#initialize
21
- @backend = Polyphony::Backend.new
21
+ raise_error = false
22
+ begin
23
+ @backend = Polyphony::Backend.new
24
+ rescue Exception => e
25
+ raise_error = true
26
+ raise e
27
+ end
22
28
  setup
23
29
  @ready = true
24
30
  result = @block.(*@args)
25
31
  rescue Polyphony::MoveOn, Polyphony::Terminate => e
26
32
  result = e.value
27
33
  rescue Exception => e
28
- result = e
34
+ raise_error ? (raise e) : (result = e)
29
35
  ensure
30
36
  @ready = true
31
37
  finalize(result)
@@ -48,7 +54,7 @@ class ::Thread
48
54
  @result = result
49
55
  signal_waiters(result)
50
56
  end
51
- @backend.finalize
57
+ @backend&.finalize
52
58
  end
53
59
 
54
60
  def signal_waiters(result)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timeout'
4
+
5
+ # Override Timeout to use cancel scope
6
+ module ::Timeout
7
+ def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
8
+ cancel_after(sec, with_exception: [klass, message], &block)
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './extensions/exception'
4
+ require_relative './extensions/fiber'
5
+ require_relative './extensions/io'
6
+ require_relative './extensions/kernel'
7
+ require_relative './extensions/process'
8
+ require_relative './extensions/thread'
9
+ require_relative './extensions/timeout'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.72'
4
+ VERSION = '0.75'
5
5
  end
data/lib/polyphony.rb CHANGED
@@ -2,15 +2,13 @@
2
2
 
3
3
  require 'fiber'
4
4
  require_relative './polyphony_ext'
5
-
6
- require_relative './polyphony/extensions/core'
7
5
  require_relative './polyphony/extensions/thread'
8
- require_relative './polyphony/extensions/fiber'
9
- require_relative './polyphony/extensions/io'
10
6
 
11
7
  Thread.current.setup_fiber_scheduling
12
8
  Thread.current.backend = Polyphony::Backend.new
13
9
 
10
+ require_relative './polyphony/extensions'
11
+ require_relative './polyphony/core/exceptions'
14
12
  require_relative './polyphony/core/global_api'
15
13
  require_relative './polyphony/core/resource_pool'
16
14
  require_relative './polyphony/core/sync'
@@ -43,6 +41,8 @@ module Polyphony
43
41
  run_forked_block(&block)
44
42
  rescue SystemExit
45
43
  # fall through to ensure
44
+ rescue Polyphony::MoveOn
45
+ exit!
46
46
  rescue Exception => e
47
47
  STDERR << e.full_message
48
48
  exit!
data/test/helper.rb CHANGED
@@ -21,10 +21,6 @@ IS_LINUX = RUBY_PLATFORM =~ /linux/
21
21
  # Minitest::Reporters::SpecReporter.new
22
22
  # ]
23
23
 
24
- class ::Fiber
25
- attr_writer :auto_watcher
26
- end
27
-
28
24
  module ::Kernel
29
25
  def trace(*args)
30
26
  STDOUT.orig_write(format_trace(args))
@@ -59,7 +55,6 @@ class MiniTest::Test
59
55
  puts "Children left after #{self.name}: #{Fiber.current.children.inspect}"
60
56
  exit!
61
57
  end
62
- Fiber.current.instance_variable_set(:@auto_watcher, nil)
63
58
  rescue => e
64
59
  puts e
65
60
  puts e.backtrace.join("\n")
data/test/test_backend.rb CHANGED
@@ -243,16 +243,14 @@ class BackendTest < MiniTest::Test
243
243
  end
244
244
 
245
245
  def test_timer_loop
246
- skip unless IS_LINUX
247
-
248
- i = 0
246
+ counter = 0
249
247
  f = spin do
250
- @backend.timer_loop(0.01) { i += 1 }
248
+ @backend.timer_loop(0.01) { counter += 1 }
251
249
  end
252
250
  @backend.sleep(0.05)
253
251
  f.stop
254
252
  f.await # TODO: check why this test sometimes segfaults if we don't a<wait fiber
255
- assert_in_range 4..6, i
253
+ assert_in_range 4..6, counter if IS_LINUX
256
254
  end
257
255
 
258
256
  class MyTimeoutException < Exception
@@ -162,7 +162,7 @@ class MoveOnAfterTest < MiniTest::Test
162
162
  end
163
163
  t1 = Time.now
164
164
  assert_equal 1, o
165
- assert_in_range 0.008..0.015, t1 - t0
165
+ assert_in_range 0.008..0.015, t1 - t0 if IS_LINUX
166
166
 
167
167
  t0 = Time.now
168
168
  o = move_on_after(0.05, with_value: 1) do
@@ -172,7 +172,7 @@ class MoveOnAfterTest < MiniTest::Test
172
172
  end
173
173
  t1 = Time.now
174
174
  assert_equal 2, o
175
- assert_in_range 0.008..0.013, t1 - t0
175
+ assert_in_range 0.008..0.013, t1 - t0 if IS_LINUX
176
176
  end
177
177
  end
178
178
 
@@ -297,7 +297,7 @@ class SpinLoopTest < MiniTest::Test
297
297
  f = spin_loop(rate: 100) { buffer << (counter += 1) }
298
298
  sleep 0.02
299
299
  f.stop
300
- assert_in_range 1..3, counter
300
+ assert_in_range 1..3, counter if IS_LINUX
301
301
  end
302
302
 
303
303
  def test_spin_loop_with_interval
@@ -307,7 +307,7 @@ class SpinLoopTest < MiniTest::Test
307
307
  f = spin_loop(interval: 0.01) { buffer << (counter += 1) }
308
308
  sleep 0.02
309
309
  f.stop
310
- assert_in_range 1..3, counter
310
+ assert_in_range 1..3, counter if IS_LINUX
311
311
  end
312
312
 
313
313
  def test_spin_loop_break
@@ -386,10 +386,10 @@ class ThrottledLoopTest < MiniTest::Test
386
386
  counter = 0
387
387
  t0 = Time.now
388
388
  f = spin do
389
- throttled_loop(100) { buffer << (counter += 1) }
389
+ throttled_loop(10) { buffer << (counter += 1) }
390
390
  end
391
- sleep 0.03
392
- assert_in_range 2..4, counter
391
+ sleep 0.3
392
+ assert_in_range 2..4, counter if IS_LINUX
393
393
  end
394
394
 
395
395
  def test_throttled_loop_with_count
@@ -412,13 +412,11 @@ class GlobalAPIEtcTest < MiniTest::Test
412
412
  f = after(0.001) { buffer << 2 }
413
413
  snooze
414
414
  assert_equal [], buffer
415
- sleep 0.001
415
+ sleep 0.0015
416
416
  assert_equal [2], buffer
417
417
  end
418
418
 
419
419
  def test_every
420
- skip unless IS_LINUX
421
-
422
420
  buffer = []
423
421
  t0 = Time.now
424
422
  f = spin do
@@ -426,14 +424,25 @@ class GlobalAPIEtcTest < MiniTest::Test
426
424
  end
427
425
  sleep 0.05
428
426
  f.stop
429
- assert_in_range 4..6, buffer.size
427
+ assert_in_range 4..6, buffer.size if IS_LINUX
428
+ end
429
+
430
+ def test_every_with_slow_op
431
+ buffer = []
432
+ t0 = Time.now
433
+ f = spin do
434
+ every(0.01) { sleep 0.05; buffer << 1 }
435
+ end
436
+ sleep 0.15
437
+ f.stop
438
+ assert_in_range 2..3, buffer.size if IS_LINUX
430
439
  end
431
440
 
432
441
  def test_sleep
433
442
  t0 = Time.now
434
443
  sleep 0.1
435
444
  elapsed = Time.now - t0
436
- assert (0.05..0.15).include? elapsed if IS_LINUX
445
+ assert_in_range 0.05..0.15, elapsed if IS_LINUX
437
446
 
438
447
  f = spin { sleep }
439
448
  snooze
data/test/test_io.rb CHANGED
@@ -354,9 +354,9 @@ class IOClassMethodsTest < MiniTest::Test
354
354
  skip unless IS_LINUX
355
355
 
356
356
  counter = 0
357
- timer = spin { throttled_loop(200) { counter += 1 } }
357
+ timer = spin { throttled_loop(20) { counter += 1 } }
358
358
 
359
- IO.popen('sleep 0.05') { |io| io.read(8192) }
359
+ IO.popen('sleep 0.5') { |io| io.read(8192) }
360
360
  assert(counter >= 5)
361
361
 
362
362
  result = nil
data/test/test_kernel.rb CHANGED
@@ -51,8 +51,8 @@ class KernelTest < MiniTest::Test
51
51
  counter = 0
52
52
  timer = spin { throttled_loop(200) { counter += 1 } }
53
53
 
54
- `sleep 0.01`
55
- assert(counter >= 2)
54
+ `sleep 0.05`
55
+ assert_in_range 8..14, counter if IS_LINUX
56
56
 
57
57
  result = `echo "hello"`
58
58
  assert_equal "hello\n", result
@@ -65,7 +65,7 @@ class ProcessSupervisionTest < MiniTest::Test
65
65
 
66
66
  supervisor = spin { supervise(watcher) }
67
67
 
68
- sleep 0.05
68
+ sleep 0.1
69
69
  supervisor.terminate
70
70
  supervisor.await
71
71
 
data/test/test_signal.rb CHANGED
@@ -93,4 +93,23 @@ class SignalTrapTest < Minitest::Test
93
93
  buffer = i.read
94
94
  assert_equal "INT\n", buffer
95
95
  end
96
- end
96
+
97
+ def test_busy_signal_handling
98
+ i, o = IO.pipe
99
+ pid = Polyphony.fork do
100
+ main = Fiber.current
101
+ trap('INT') { o.puts 'INT'; o.close; main.stop }
102
+ i.close
103
+ f1 = spin_loop { snooze }
104
+ f2 = spin_loop { snooze }
105
+ f1.await
106
+ end
107
+
108
+ o.close
109
+ sleep 0.1
110
+ Process.kill('INT', pid)
111
+ Thread.current.backend.waitpid(pid)
112
+ buffer = i.read
113
+ assert_equal "INT\n", buffer
114
+ end
115
+ end
data/test/test_socket.rb CHANGED
@@ -9,9 +9,9 @@ class SocketTest < MiniTest::Test
9
9
  super
10
10
  end
11
11
 
12
- def start_tcp_server_on_random_port
12
+ def start_tcp_server_on_random_port(host = '127.0.0.1')
13
13
  port = rand(1100..60000)
14
- server = TCPServer.new('127.0.0.1', port)
14
+ server = TCPServer.new(host, port)
15
15
  [port, server]
16
16
  rescue Errno::EADDRINUSE
17
17
  retry
@@ -40,6 +40,39 @@ class SocketTest < MiniTest::Test
40
40
  server&.close
41
41
  end
42
42
 
43
+ def test_tcpsocket_open_with_hostname
44
+ client = TCPSocket.open('google.com', 80)
45
+ client.write("GET / HTTP/1.0\r\nHost: google.com\r\n\r\n")
46
+ result = nil
47
+ move_on_after(1) {
48
+ result = client.read
49
+ }
50
+ assert result =~ /HTTP\/1.0 301 Moved Permanently/
51
+ end
52
+
53
+ def test_tcp_ipv6
54
+ port, server = start_tcp_server_on_random_port('::1')
55
+ server_fiber = spin do
56
+ while (socket = server.accept)
57
+ spin do
58
+ while (data = socket.gets(8192))
59
+ socket << data
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ snooze
66
+ client = TCPSocket.new('::1', port)
67
+ client.write("1234\n")
68
+ assert_equal "1234\n", client.recv(8192)
69
+ client.close
70
+ ensure
71
+ server_fiber&.stop
72
+ server_fiber&.await
73
+ server&.close
74
+ end
75
+
43
76
  def test_read
44
77
  port, server = start_tcp_server_on_random_port
45
78
  server_fiber = spin do
data/test/test_thread.rb CHANGED
@@ -132,7 +132,7 @@ class ThreadTest < MiniTest::Test
132
132
  Thread.backend.trace_proc = proc {|*r| records << r }
133
133
  suspend
134
134
  assert_equal [
135
- [:fiber_switchpoint, Fiber.current]
135
+ [:fiber_switchpoint, Fiber.current, ["#{__FILE__}:#{__LINE__ - 2}:in `test_that_suspend_returns_immediately_if_no_watchers'"] + caller]
136
136
  ], records
137
137
  ensure
138
138
  Thread.backend.trace_proc = nil
@@ -65,7 +65,7 @@ class ThreadPoolTest < MiniTest::Test
65
65
  end
66
66
  elapsed = Time.now - t0
67
67
 
68
- assert_in_range 0.0..0.009, elapsed
68
+ assert_in_range 0.0..0.009, elapsed if IS_LINUX
69
69
  assert buffer.size < 2
70
70
 
71
71
  sleep 0.15 # allow time for threads to spawn
@@ -10,7 +10,7 @@ class ThrottlerTest < MiniTest::Test
10
10
  f = spin { loop { t.process { buffer << 1 } } }
11
11
  sleep 0.2
12
12
  f.stop
13
- assert_in_range 1..4, buffer.size
13
+ assert_in_range 1..4, buffer.size if IS_LINUX
14
14
  ensure
15
15
  t.stop
16
16
  end
@@ -23,7 +23,7 @@ class ThrottlerTest < MiniTest::Test
23
23
  end
24
24
  sleep 0.25
25
25
  f.stop
26
- assert_in_range 2..7, buffer.size
26
+ assert_in_range 4..6, buffer.size if IS_LINUX
27
27
  ensure
28
28
  t.stop
29
29
  end
@@ -34,7 +34,7 @@ class ThrottlerTest < MiniTest::Test
34
34
  f = spin { loop { t.process { buffer << 1 } } }
35
35
  sleep 0.02
36
36
  f.stop
37
- assert_in_range 2..4, buffer.size
37
+ assert_in_range 2..4, buffer.size if IS_LINUX
38
38
  ensure
39
39
  t.stop
40
40
  end
data/test/test_timer.rb CHANGED
@@ -160,6 +160,6 @@ class TimerMiscTest < MiniTest::Test
160
160
  end
161
161
  sleep 0.05
162
162
  f.stop
163
- assert_in_range 3..7, buffer.size
163
+ assert_in_range 3..7, buffer.size if IS_LINUX
164
164
  end
165
165
  end
data/test/test_trace.rb CHANGED
@@ -10,7 +10,7 @@ class TraceTest < MiniTest::Test
10
10
 
11
11
  assert_equal [
12
12
  [:fiber_schedule, Fiber.current, nil, false],
13
- [:fiber_switchpoint, Fiber.current],
13
+ [:fiber_switchpoint, Fiber.current, ["#{__FILE__}:#{__LINE__ - 4}:in `test_tracing_enabled'"] + caller],
14
14
  [:fiber_run, Fiber.current, nil]
15
15
  ], events
16
16
  ensure
@@ -22,9 +22,15 @@ class TraceTest < MiniTest::Test
22
22
  Thread.backend.trace_proc = proc { |*e| events << e }
23
23
 
24
24
  f = spin { sleep 0; :byebye }
25
+ l0 = __LINE__ + 1
25
26
  suspend
26
27
  sleep 0
27
28
 
29
+ Thread.backend.trace_proc = nil
30
+
31
+ # remove caller info for :fiber_switchpoint events
32
+ events.each {|e| e.pop if e[0] == :fiber_switchpoint }
33
+
28
34
  assert_equal [
29
35
  [:fiber_create, f],
30
36
  [:fiber_schedule, f, nil, false],
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: '0.72'
4
+ version: '0.75'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-22 00:00:00.000000000 Z
11
+ date: 2022-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -146,6 +146,7 @@ extra_rdoc_files:
146
146
  files:
147
147
  - ".github/FUNDING.yml"
148
148
  - ".github/workflows/test.yml"
149
+ - ".github/workflows/test_io_uring.yml"
149
150
  - ".gitignore"
150
151
  - ".gitmodules"
151
152
  - ".rubocop.yml"
@@ -233,6 +234,7 @@ files:
233
234
  - examples/core/queue.rb
234
235
  - examples/core/recurrent-timer.rb
235
236
  - examples/core/resource_delegate.rb
237
+ - examples/core/ring.rb
236
238
  - examples/core/spin.rb
237
239
  - examples/core/spin_error_backtrace.rb
238
240
  - examples/core/supervise-process.rb
@@ -354,6 +356,7 @@ files:
354
356
  - lib/polyphony/adapters/redis.rb
355
357
  - lib/polyphony/adapters/sequel.rb
356
358
  - lib/polyphony/core/channel.rb
359
+ - lib/polyphony/core/debug.rb
357
360
  - lib/polyphony/core/exceptions.rb
358
361
  - lib/polyphony/core/global_api.rb
359
362
  - lib/polyphony/core/resource_pool.rb
@@ -362,13 +365,16 @@ files:
362
365
  - lib/polyphony/core/throttler.rb
363
366
  - lib/polyphony/core/timer.rb
364
367
  - lib/polyphony/debugger.rb
365
- - lib/polyphony/extensions/core.rb
366
- - lib/polyphony/extensions/debug.rb
368
+ - lib/polyphony/extensions.rb
369
+ - lib/polyphony/extensions/exception.rb
367
370
  - lib/polyphony/extensions/fiber.rb
368
371
  - lib/polyphony/extensions/io.rb
372
+ - lib/polyphony/extensions/kernel.rb
369
373
  - lib/polyphony/extensions/openssl.rb
374
+ - lib/polyphony/extensions/process.rb
370
375
  - lib/polyphony/extensions/socket.rb
371
376
  - lib/polyphony/extensions/thread.rb
377
+ - lib/polyphony/extensions/timeout.rb
372
378
  - lib/polyphony/net.rb
373
379
  - lib/polyphony/version.rb
374
380
  - polyphony.gemspec
@@ -425,7 +431,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
425
431
  - !ruby/object:Gem::Version
426
432
  version: '0'
427
433
  requirements: []
428
- rubygems_version: 3.1.2
434
+ rubygems_version: 3.2.32
429
435
  signing_key:
430
436
  specification_version: 4
431
437
  summary: Fine grained concurrency for Ruby