polyphony 0.77 → 0.80

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/CHANGELOG.md +18 -0
  4. data/Gemfile.lock +2 -1
  5. data/examples/core/pingpong.rb +7 -4
  6. data/examples/core/zlib_stream.rb +15 -0
  7. data/ext/polyphony/backend_common.c +16 -8
  8. data/ext/polyphony/backend_common.h +8 -3
  9. data/ext/polyphony/backend_io_uring.c +19 -3
  10. data/ext/polyphony/backend_libev.c +33 -17
  11. data/ext/polyphony/fiber.c +28 -28
  12. data/ext/polyphony/polyphony.c +1 -8
  13. data/ext/polyphony/polyphony.h +11 -8
  14. data/ext/polyphony/queue.c +82 -6
  15. data/ext/polyphony/thread.c +6 -2
  16. data/lib/polyphony/adapters/fs.rb +4 -0
  17. data/lib/polyphony/adapters/process.rb +14 -1
  18. data/lib/polyphony/adapters/redis.rb +28 -0
  19. data/lib/polyphony/adapters/sequel.rb +19 -1
  20. data/lib/polyphony/core/debug.rb +203 -0
  21. data/lib/polyphony/core/exceptions.rb +21 -6
  22. data/lib/polyphony/core/global_api.rb +228 -73
  23. data/lib/polyphony/core/resource_pool.rb +65 -20
  24. data/lib/polyphony/core/sync.rb +57 -12
  25. data/lib/polyphony/core/thread_pool.rb +42 -5
  26. data/lib/polyphony/core/throttler.rb +21 -5
  27. data/lib/polyphony/core/timer.rb +125 -1
  28. data/lib/polyphony/extensions/exception.rb +36 -6
  29. data/lib/polyphony/extensions/fiber.rb +244 -61
  30. data/lib/polyphony/extensions/io.rb +4 -2
  31. data/lib/polyphony/extensions/kernel.rb +9 -4
  32. data/lib/polyphony/extensions/object.rb +8 -0
  33. data/lib/polyphony/extensions/openssl.rb +3 -1
  34. data/lib/polyphony/extensions/socket.rb +458 -39
  35. data/lib/polyphony/extensions/thread.rb +108 -43
  36. data/lib/polyphony/extensions/timeout.rb +12 -1
  37. data/lib/polyphony/extensions.rb +1 -0
  38. data/lib/polyphony/net.rb +59 -0
  39. data/lib/polyphony/version.rb +1 -1
  40. data/lib/polyphony.rb +0 -2
  41. data/test/test_backend.rb +6 -2
  42. data/test/test_global_api.rb +0 -23
  43. data/test/test_io.rb +7 -7
  44. data/test/test_queue.rb +103 -1
  45. data/test/test_resource_pool.rb +1 -1
  46. data/test/test_signal.rb +15 -15
  47. data/test/test_supervise.rb +27 -0
  48. data/test/test_thread.rb +1 -1
  49. data/test/test_throttler.rb +0 -6
  50. data/test/test_trace.rb +189 -24
  51. metadata +9 -8
  52. data/lib/polyphony/core/channel.rb +0 -15
@@ -5,8 +5,11 @@ require_relative '../core/exceptions'
5
5
  # Thread extensions
6
6
  class ::Thread
7
7
  attr_reader :main_fiber, :result
8
+ attr_accessor :backend
8
9
 
9
10
  alias_method :orig_initialize, :initialize
11
+
12
+ # Initializes the thread.
10
13
  def initialize(*args, &block)
11
14
  @join_wait_queue = []
12
15
  @finalization_mutex = Mutex.new
@@ -15,53 +18,30 @@ class ::Thread
15
18
  orig_initialize { execute }
16
19
  end
17
20
 
18
- def execute
19
- # backend must be created in the context of the new thread, therefore it
20
- # cannot be created in Thread#initialize
21
- raise_error = false
22
- begin
23
- @backend = Polyphony::Backend.new
24
- rescue Exception => e
25
- raise_error = true
26
- raise e
27
- end
28
- setup
29
- @ready = true
30
- result = @block.(*@args)
31
- rescue Polyphony::MoveOn, Polyphony::Terminate => e
32
- result = e.value
33
- rescue Exception => e
34
- raise_error ? (raise e) : (result = e)
35
- ensure
36
- @ready = true
37
- finalize(result)
38
- end
39
-
40
- attr_accessor :backend
41
-
21
+ # Sets up the thread and its main fiber.
22
+ #
23
+ # @return [void]
42
24
  def setup
43
25
  @main_fiber = Fiber.current
44
26
  @main_fiber.setup_main_fiber
45
27
  setup_fiber_scheduling
46
28
  end
47
29
 
48
- def finalize(result)
49
- unless Fiber.current.children.empty?
50
- Fiber.current.shutdown_all_children
51
- end
52
- @finalization_mutex.synchronize do
53
- @terminated = true
54
- @result = result
55
- signal_waiters(result)
56
- end
57
- @backend&.finalize
58
- end
59
-
60
- def signal_waiters(result)
61
- @join_wait_queue.each { |w| w.signal(result) }
62
- end
63
-
64
30
  alias_method :orig_join, :join
31
+
32
+ # call-seq:
33
+ # thread.join -> result
34
+ # thread.join(timeout) -> result
35
+ # thread.await -> result
36
+ # thread.await(timeout) -> result
37
+ #
38
+ # Waits for the thread to terminate and returns its return value. If the
39
+ # thread terminated with an uncaught exception, it is propagated to the
40
+ # waiting fiber. If a timeout interval is specified, the thread will be
41
+ # terminated without propagating the timeout exception.
42
+ #
43
+ # @param timeout [Number] timeout interval
44
+ # @return [any] thread's return value
65
45
  def join(timeout = nil)
66
46
  watcher = Fiber.current.auto_watcher
67
47
 
@@ -77,6 +57,16 @@ class ::Thread
77
57
  alias_method :await, :join
78
58
 
79
59
  alias_method :orig_raise, :raise
60
+
61
+ # call-seq:
62
+ # thread.raise
63
+ # thread.raise(exception_class)
64
+ # thread.raise(exception_instance)
65
+ #
66
+ # Raises an exception in the context of the thread. If no exception is given,
67
+ # a `RuntimeError` is raised.
68
+ #
69
+ # @param error [Exception, Class, nil] exception spec
80
70
  def raise(error = nil)
81
71
  Thread.pass until @main_fiber
82
72
  error = RuntimeError.new if error.nil?
@@ -88,13 +78,22 @@ class ::Thread
88
78
  end
89
79
 
90
80
  alias_method :orig_kill, :kill
81
+
82
+ # Terminates the thread.
83
+ #
84
+ # @return [Thread] self
91
85
  def kill
92
- return if @terminated
86
+ return self if @terminated
93
87
 
94
88
  raise Polyphony::Terminate
89
+ self
95
90
  end
96
91
 
97
92
  alias_method :orig_inspect, :inspect
93
+
94
+ # Returns a string representation of the thread for debugging purposes.
95
+ #
96
+ # @return [String] string representation
98
97
  def inspect
99
98
  return orig_inspect if self == Thread.main
100
99
 
@@ -103,20 +102,86 @@ class ::Thread
103
102
  end
104
103
  alias_method :to_s, :inspect
105
104
 
105
+ # Returns the source location of the thread's block.
106
+ #
107
+ # @return [String] source location
106
108
  def location
107
109
  @block.source_location.join(':')
108
110
  end
109
111
 
110
- def <<(value)
111
- main_fiber << value
112
+ # Sends a message to the thread's main fiber.
113
+ #
114
+ # @param msg [any] message
115
+ # @return [Fiber] main fiber
116
+ def <<(msg)
117
+ main_fiber << msg
112
118
  end
113
119
  alias_method :send, :<<
114
120
 
121
+ # Sets the idle GC period for the thread's backend.
122
+ #
123
+ # @param period [Number] GC period in seconds
124
+ # @return [Number] GC period
115
125
  def idle_gc_period=(period)
116
126
  backend.idle_gc_period = period
117
127
  end
118
128
 
129
+ # Sets the idle handler for the thread's backend.
130
+ #
131
+ # @param &block [Proc] idle handler
132
+ # @return [Proc] idle handler
119
133
  def on_idle(&block)
120
134
  backend.idle_proc = block
121
135
  end
136
+
137
+ private
138
+
139
+ # Runs the thread's block, handling any uncaught exceptions.
140
+ #
141
+ # @return [void]
142
+ def execute
143
+ # backend must be created in the context of the new thread, therefore it
144
+ # cannot be created in Thread#initialize
145
+ raise_error = false
146
+ begin
147
+ @backend = Polyphony::Backend.new
148
+ rescue Exception => e
149
+ raise_error = true
150
+ raise e
151
+ end
152
+ setup
153
+ @ready = true
154
+ result = @block.(*@args)
155
+ rescue Polyphony::MoveOn, Polyphony::Terminate => e
156
+ result = e.value
157
+ rescue Exception => e
158
+ raise_error ? (raise e) : (result = e)
159
+ ensure
160
+ @ready = true
161
+ finalize(result)
162
+ end
163
+
164
+ # Finalizes the thread.
165
+ #
166
+ # @param result [any] thread's return value
167
+ # @return [void]
168
+ def finalize(result)
169
+ unless Fiber.current.children.empty?
170
+ Fiber.current.shutdown_all_children
171
+ end
172
+ @finalization_mutex.synchronize do
173
+ @terminated = true
174
+ @result = result
175
+ signal_waiters(result)
176
+ end
177
+ @backend&.finalize
178
+ end
179
+
180
+ # Signals all fibers waiting for the thread to terminate.
181
+ #
182
+ # @param result [any] thread's return value
183
+ # @return [void]
184
+ def signal_waiters(result)
185
+ @join_wait_queue.each { |w| w.signal(result) }
186
+ end
122
187
  end
@@ -2,8 +2,19 @@
2
2
 
3
3
  require 'timeout'
4
4
 
5
- # Override Timeout to use cancel scope
5
+ # Timeout extensions
6
6
  module ::Timeout
7
+
8
+ # Sets a timeout for the given block. This method provides an equivalent API
9
+ # to the stock Timeout API provided by Ruby. In case of a timeout, the block
10
+ # will be interrupted and an exception will be raised according to the given
11
+ # arguments.
12
+ #
13
+ # @param sec [Number] timeout period in seconds
14
+ # @param klass [Class] exception class
15
+ # @param message [String] exception message
16
+ # @param &block [Proc] code to run
17
+ # @return [any] block's return value
7
18
  def self.timeout(sec, klass = Timeout::Error, message = 'execution expired', &block)
8
19
  cancel_after(sec, with_exception: [klass, message], &block)
9
20
  end
@@ -3,6 +3,7 @@
3
3
  require_relative './extensions/exception'
4
4
  require_relative './extensions/fiber'
5
5
  require_relative './extensions/io'
6
+ require_relative './extensions/object'
6
7
  require_relative './extensions/kernel'
7
8
  require_relative './extensions/process'
8
9
  require_relative './extensions/thread'
data/lib/polyphony/net.rb CHANGED
@@ -4,9 +4,25 @@ require_relative './extensions/socket'
4
4
  require_relative './extensions/openssl'
5
5
 
6
6
  module Polyphony
7
+
7
8
  # A more elegant networking API
8
9
  module Net
9
10
  class << self
11
+
12
+ # call-seq:
13
+ # Polyphony::Net.tcp_connect(host, port) -> TCPSocket
14
+ # Polyphony::Net.tcp_connect(host, port, secure: true) -> SSLSocket
15
+ # Polyphony::Net.tcp_connect(host, port, secure_context: ctx) -> SSLSocket
16
+ #
17
+ # Create a TCP connection to the given host and port, returning the new
18
+ # socket. If `opts[:secure]` is true, or if an SSL context is given in
19
+ # `opts[:secure_context]`, a TLS handshake is performed, and an SSLSocket
20
+ # is returned.
21
+ #
22
+ # @param host [String] hostname
23
+ # @param port [Integer] port number
24
+ # @param opts [Hash] connection options
25
+ # @return [TCPSocket, SSLSocket] connected socket
10
26
  def tcp_connect(host, port, opts = {})
11
27
  socket = TCPSocket.new(host, port)
12
28
  if opts[:secure_context] || opts[:secure]
@@ -16,6 +32,15 @@ module Polyphony
16
32
  end
17
33
  end
18
34
 
35
+ # Creates a server socket for accepting incoming connection on the given
36
+ # host and port. If `opts[:secure]` is true, or if an SSL context is given
37
+ # in `opts[:secure_context]`, a TLS handshake is performed, and an
38
+ # SSLSocket is returned.
39
+ #
40
+ # @param host [String] hostname
41
+ # @param port [Integer] port number
42
+ # @param opts [Hash] connection options
43
+ # @return [TCPServer, SSLServer] listening socket
19
44
  def tcp_listen(host = nil, port = nil, opts = {})
20
45
  host ||= '0.0.0.0'
21
46
  raise 'Port number not specified' unless port
@@ -28,6 +53,14 @@ module Polyphony
28
53
  end
29
54
  end
30
55
 
56
+ private
57
+
58
+ # Creates a listening `Socket` instance.
59
+ #
60
+ # @param host [String] hostname
61
+ # @param port [Integer] port number
62
+ # @param opts [Hash] connection options
63
+ # @return [Socket] listening socket
31
64
  def listening_socket_from_options(host, port, opts)
32
65
  ::Socket.new(:INET, :STREAM).tap do |s|
33
66
  s.reuse_addr if opts[:reuse_addr]
@@ -39,6 +72,12 @@ module Polyphony
39
72
  end
40
73
  end
41
74
 
75
+ # Wraps the given socket with a SSLSocket and performs a TLS handshake.
76
+ #
77
+ # @param socket [Socket] plain socket
78
+ # @param context [SSLContext, nil] SSL context
79
+ # @param opts [Hash] connection options
80
+ # @return [SSLSocket] SSL socket
42
81
  def secure_socket(socket, context, opts)
43
82
  context ||= OpenSSL::SSL::SSLContext.new
44
83
  setup_alpn(context, opts[:alpn_protocols]) if opts[:alpn_protocols]
@@ -51,6 +90,11 @@ module Polyphony
51
90
  end
52
91
  end
53
92
 
93
+ # Wraps the given socket with an SSLSocket.
94
+ #
95
+ # @param socket [Socket] plain socket
96
+ # @param context [SSLContext] SSL context
97
+ # @return [SSLSocket] SSL socket
54
98
  def secure_socket_wrapper(socket, context)
55
99
  if context
56
100
  OpenSSL::SSL::SSLSocket.new(socket, context)
@@ -59,11 +103,26 @@ module Polyphony
59
103
  end
60
104
  end
61
105
 
106
+ # Wraps the given socket with an SSLServer, setting up ALPN from the given
107
+ # options.
108
+ #
109
+ # @param socket [Socket] plain socket
110
+ # @param context [SSLContext] SSL context
111
+ # @param opts [Hash] options
112
+ # @return [SSLServer] SSL socket
62
113
  def secure_server(socket, context, opts)
63
114
  setup_alpn(context, opts[:alpn_protocols]) if opts[:alpn_protocols]
64
115
  OpenSSL::SSL::SSLServer.new(socket, context)
65
116
  end
66
117
 
118
+ # Sets up ALPN negotiation for the given context. The ALPN handler for the
119
+ # context will select the first protocol from the list given by the client
120
+ # that appears in the list of given protocols, according to the specified
121
+ # order.
122
+ #
123
+ # @param context [SSLContext] SSL context
124
+ # @param protocols [Array] array of supported protocols
125
+ # @return [void]
67
126
  def setup_alpn(context, protocols)
68
127
  context.alpn_protocols = protocols
69
128
  context.alpn_select_cb = lambda do |peer_protocols|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.77'
4
+ VERSION = '0.80'
5
5
  end
data/lib/polyphony.rb CHANGED
@@ -9,7 +9,6 @@ Thread.current.backend = Polyphony::Backend.new
9
9
 
10
10
  require_relative './polyphony/extensions'
11
11
  require_relative './polyphony/core/exceptions'
12
- require_relative './polyphony/core/global_api'
13
12
  require_relative './polyphony/core/resource_pool'
14
13
  require_relative './polyphony/core/sync'
15
14
  require_relative './polyphony/core/timer'
@@ -53,7 +52,6 @@ module Polyphony
53
52
 
54
53
  def run_forked_block(&block)
55
54
  Thread.current.setup
56
- Fiber.current.setup_main_fiber
57
55
  Thread.current.backend.post_fork
58
56
 
59
57
  install_terminating_signal_handlers
data/test/test_backend.rb CHANGED
@@ -191,7 +191,9 @@ class BackendTest < MiniTest::Test
191
191
  Net = Polyphony::Net
192
192
 
193
193
  def test_accept
194
- server = Net.listening_socket_from_options('127.0.0.1', 1234, reuse_addr: true)
194
+ server = Net.send(
195
+ :listening_socket_from_options, '127.0.0.1', 1234, reuse_addr: true
196
+ )
195
197
 
196
198
  clients = []
197
199
  server_fiber = spin_loop do
@@ -218,7 +220,9 @@ class BackendTest < MiniTest::Test
218
220
  end
219
221
 
220
222
  def test_accept_loop
221
- server = Net.listening_socket_from_options('127.0.0.1', 1235, reuse_addr: true)
223
+ server = Net.send(
224
+ :listening_socket_from_options, '127.0.0.1', 1235, reuse_addr: true
225
+ )
222
226
 
223
227
  clients = []
224
228
  server_fiber = spin do
@@ -140,17 +140,6 @@ class MoveOnAfterTest < MiniTest::Test
140
140
  assert_in_range 0.014..0.02, t1 - t0 if IS_LINUX
141
141
  end
142
142
 
143
- def test_move_on_after_without_block
144
- t0 = Time.now
145
- f = move_on_after(0.01, with_value: 'foo')
146
- assert_kind_of Fiber, f
147
- assert_equal Fiber.current, f.parent
148
- v = sleep 1
149
- t1 = Time.now
150
- assert t1 - t0 < 0.1
151
- assert_equal 'foo', v
152
- end
153
-
154
143
  def test_nested_move_on_after
155
144
  skip unless IS_LINUX
156
145
 
@@ -190,18 +179,6 @@ class CancelAfterTest < MiniTest::Test
190
179
  assert t1 - t0 < 0.1
191
180
  end
192
181
 
193
- def test_cancel_after_without_block
194
- t0 = Time.now
195
- f = cancel_after(0.01)
196
- assert_kind_of Fiber, f
197
- assert_equal Fiber.current, f.parent
198
- assert_raises Polyphony::Cancel do
199
- sleep 1
200
- end
201
- t1 = Time.now
202
- assert t1 - t0 < 0.1
203
- end
204
-
205
182
  def test_cancel_after_with_reset
206
183
  t0 = Time.now
207
184
  cancel_after(0.01) do |f|
data/test/test_io.rb CHANGED
@@ -309,13 +309,13 @@ class IOClassMethodsTest < MiniTest::Test
309
309
  assert_equal BIN_DATA, s
310
310
  end
311
311
 
312
- def test_foreach
313
- skip 'IO.foreach is not yet implemented'
314
- lines = []
315
- IO.foreach(__FILE__) { |l| lines << l }
316
- assert_equal "# frozen_string_literal: true\n", lines[0]
317
- assert_equal "end\n", lines[-1]
318
- end
312
+ # def test_foreach
313
+ # skip 'IO.foreach is not yet implemented'
314
+ # lines = []
315
+ # IO.foreach(__FILE__) { |l| lines << l }
316
+ # assert_equal "# frozen_string_literal: true\n", lines[0]
317
+ # assert_equal "end\n", lines[-1]
318
+ # end
319
319
 
320
320
  def test_read_class_method
321
321
  s = IO.read(__FILE__)
data/test/test_queue.rb CHANGED
@@ -21,6 +21,44 @@ class QueueTest < MiniTest::Test
21
21
  assert_equal [1, 2, 3, 4], buf
22
22
  end
23
23
 
24
+ def test_chained_push
25
+ @queue << 5 << 6 << 7
26
+
27
+ buf = []
28
+ 3.times { buf << @queue.shift }
29
+ assert_equal [5, 6, 7], buf
30
+ end
31
+
32
+ def test_push_aliases
33
+ @queue.push 1
34
+ @queue << 2
35
+ @queue.enq 3
36
+
37
+ buf = []
38
+ 3.times { buf << @queue.shift }
39
+ assert_equal [1, 2, 3], buf
40
+ end
41
+
42
+ def test_pop_aliases
43
+ @queue << 1 << 2 << 3
44
+
45
+ assert_equal 1, @queue.pop
46
+ assert_equal 2, @queue.deq
47
+ assert_equal 3, @queue.shift
48
+
49
+ @queue << 1 << 2 << 3
50
+
51
+ assert_equal 1, @queue.pop(false)
52
+ assert_equal 2, @queue.deq(false)
53
+ assert_equal 3, @queue.shift(false)
54
+ end
55
+
56
+ def test_nonblocking_pop
57
+ assert_raises(ThreadError) { @queue.pop(true) }
58
+ assert_raises(ThreadError) { @queue.deq(true) }
59
+ assert_raises(ThreadError) { @queue.shift(true) }
60
+ end
61
+
24
62
  def test_unshift
25
63
  @queue.push 1
26
64
  @queue.push 2
@@ -112,22 +150,86 @@ class QueueTest < MiniTest::Test
112
150
 
113
151
  def test_queue_size
114
152
  assert_equal 0, @queue.size
153
+ assert_equal 0, @queue.length
115
154
 
116
155
  @queue.push 1
117
156
 
118
157
  assert_equal 1, @queue.size
158
+ assert_equal 1, @queue.length
119
159
 
120
160
  @queue.push 2
121
161
 
122
162
  assert_equal 2, @queue.size
163
+ assert_equal 2, @queue.length
123
164
 
124
165
  @queue.shift
125
166
 
126
167
  assert_equal 1, @queue.size
168
+ assert_equal 1, @queue.length
127
169
 
128
170
  @queue.shift
129
171
 
130
172
  assert_equal 0, @queue.size
173
+ assert_equal 0, @queue.length
174
+ end
175
+
176
+ def test_pending?
177
+ assert_equal false, @queue.pending?
178
+
179
+ buf = []
180
+ f = spin { buf << @queue.shift }
181
+ snooze
182
+ assert_equal true, @queue.pending?
183
+
184
+ @queue << 42
185
+ f.await
186
+ assert_equal [42], buf
187
+ assert_equal false, @queue.pending?
188
+ end
189
+
190
+ def test_num_waiting
191
+ assert_equal 0, @queue.num_waiting
192
+
193
+ f1 = spin { @queue.shift }
194
+ snooze # allow fiber to start
195
+ assert_equal 1, @queue.num_waiting
196
+
197
+ f2 = spin { @queue.shift }
198
+ snooze # allow fiber to start
199
+ assert_equal 2, @queue.num_waiting
200
+
201
+ @queue << 1
202
+ f1.await
203
+ assert_equal 1, @queue.num_waiting
204
+
205
+ @queue << 2
206
+ f2.await
207
+ assert_equal 0, @queue.num_waiting
208
+ end
209
+
210
+ def test_closed_queue
211
+ assert_equal false, @queue.closed?
212
+
213
+ buf = []
214
+ f = spin { buf << @queue.shift }
215
+ snooze # allow fiber to start
216
+
217
+ @queue.close
218
+ assert_equal true, @queue.closed?
219
+ cancel_after(1) { f.await }
220
+ assert_equal [nil], buf
221
+
222
+ assert_raises(ClosedQueueError) { @queue << 1 }
223
+ assert_raises(ClosedQueueError) { @queue.deq }
224
+ assert_raises(ThreadError) { @queue.pop(true) }
225
+
226
+ # test deq on closed non-empty queue
227
+ @queue = Polyphony::Queue.new
228
+ @queue << 42 << 43
229
+ @queue.close
230
+
231
+ assert_equal 42, @queue.deq(false)
232
+ assert_equal 43, @queue.deq(true)
131
233
  end
132
234
  end
133
235
 
@@ -246,4 +348,4 @@ class CappedQueueTest < MiniTest::Test
246
348
  a.join
247
349
  assert_equal [1, 2, 3, :d5, 4, :d8, 5], buffer
248
350
  end
249
- end
351
+ end
@@ -88,7 +88,7 @@ class ResourcePoolTest < MiniTest::Test
88
88
  assert_equal 2, pool.limit
89
89
  assert_equal 0, pool.size
90
90
 
91
- pool.preheat!
91
+ pool.fill!
92
92
  assert_equal 2, pool.size
93
93
  end
94
94
 
data/test/test_signal.rb CHANGED
@@ -33,24 +33,24 @@ class SignalTrapTest < Minitest::Test
33
33
  Fiber.current.tag = :main
34
34
 
35
35
  expected = [
36
- [:fiber_switchpoint, :main],
37
- [:fiber_event_poll_enter, :main],
38
- [:fiber_create, :oob],
39
- [:fiber_schedule, :oob],
40
- [:fiber_event_poll_leave, :main],
41
- [:fiber_run, :oob],
42
- [:fiber_terminate, :oob],
43
- [:fiber_switchpoint, :oob],
44
- [:fiber_event_poll_enter, :oob],
45
- [:fiber_schedule, :main],
46
- [:fiber_event_poll_leave, :oob],
47
- [:fiber_run, :main]
36
+ [:block, :main],
37
+ [:enter_poll, :main],
38
+ [:spin, :oob],
39
+ [:schedule, :oob],
40
+ [:leave_poll, :main],
41
+ [:unblock, :oob],
42
+ [:terminate, :oob],
43
+ [:block, :oob],
44
+ [:enter_poll, :oob],
45
+ [:schedule, :main],
46
+ [:leave_poll, :oob],
47
+ [:unblock, :main]
48
48
  ]
49
49
  if Thread.backend.kind == :libev
50
50
  expected += [
51
- [:fiber_schedule, :main],
52
- [:fiber_switchpoint, :main],
53
- [:fiber_run, :main]
51
+ [:schedule, :main],
52
+ [:block, :main],
53
+ [:unblock, :main]
54
54
  ]
55
55
  end
56
56
 
@@ -269,4 +269,31 @@ class SuperviseTest < MiniTest::Test
269
269
  snooze
270
270
  assert_equal [[f1, :foo], [f2, :bar]], buffer
271
271
  end
272
+
273
+ def test_detached_supervisor
274
+ buffer = []
275
+
276
+ s = nil
277
+ f = spin {
278
+ foo = spin do
279
+ sleep 0.1
280
+ ensure
281
+ buffer << :foo
282
+ end
283
+ bar = spin do
284
+ sleep 0.2
285
+ ensure
286
+ buffer << :bar
287
+ end
288
+
289
+ s = spin { supervise }.detach
290
+ Fiber.current.attach_all_children_to(s)
291
+
292
+ s.terminate(true)
293
+ }
294
+
295
+ f.await
296
+ s.await
297
+ assert_equal [:foo, :bar], buffer
298
+ end
272
299
  end
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, ["#{__FILE__}:#{__LINE__ - 2}:in `test_that_suspend_returns_immediately_if_no_watchers'"] + caller]
135
+ [:block, 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