polyphony 0.79 → 0.80

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile.lock +2 -1
  4. data/examples/core/zlib_stream.rb +15 -0
  5. data/ext/polyphony/backend_common.c +2 -1
  6. data/ext/polyphony/backend_common.h +7 -2
  7. data/lib/polyphony/adapters/fs.rb +4 -0
  8. data/lib/polyphony/adapters/process.rb +14 -1
  9. data/lib/polyphony/adapters/redis.rb +28 -0
  10. data/lib/polyphony/adapters/sequel.rb +19 -1
  11. data/lib/polyphony/core/debug.rb +129 -72
  12. data/lib/polyphony/core/exceptions.rb +21 -6
  13. data/lib/polyphony/core/global_api.rb +228 -73
  14. data/lib/polyphony/core/resource_pool.rb +65 -20
  15. data/lib/polyphony/core/sync.rb +57 -12
  16. data/lib/polyphony/core/thread_pool.rb +42 -5
  17. data/lib/polyphony/core/throttler.rb +21 -5
  18. data/lib/polyphony/core/timer.rb +125 -1
  19. data/lib/polyphony/extensions/exception.rb +36 -6
  20. data/lib/polyphony/extensions/fiber.rb +238 -57
  21. data/lib/polyphony/extensions/io.rb +4 -2
  22. data/lib/polyphony/extensions/kernel.rb +9 -4
  23. data/lib/polyphony/extensions/object.rb +8 -0
  24. data/lib/polyphony/extensions/openssl.rb +3 -1
  25. data/lib/polyphony/extensions/socket.rb +458 -39
  26. data/lib/polyphony/extensions/thread.rb +108 -43
  27. data/lib/polyphony/extensions/timeout.rb +12 -1
  28. data/lib/polyphony/extensions.rb +1 -0
  29. data/lib/polyphony/net.rb +59 -0
  30. data/lib/polyphony/version.rb +1 -1
  31. data/lib/polyphony.rb +0 -2
  32. data/test/test_backend.rb +6 -2
  33. data/test/test_global_api.rb +0 -23
  34. data/test/test_resource_pool.rb +1 -1
  35. data/test/test_throttler.rb +0 -6
  36. data/test/test_trace.rb +87 -0
  37. metadata +9 -8
  38. 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.79'
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|
@@ -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
 
@@ -11,8 +11,6 @@ class ThrottlerTest < MiniTest::Test
11
11
  sleep 0.2
12
12
  f.stop
13
13
  assert_in_range 1..4, buffer.size if IS_LINUX
14
- ensure
15
- t.stop
16
14
  end
17
15
 
18
16
  def test_throttler_with_hash_of_rate
@@ -24,8 +22,6 @@ class ThrottlerTest < MiniTest::Test
24
22
  sleep 0.25
25
23
  f.stop
26
24
  assert_in_range 4..6, buffer.size if IS_LINUX
27
- ensure
28
- t.stop
29
25
  end
30
26
 
31
27
  def test_throttler_with_hash_of_interval
@@ -35,8 +31,6 @@ class ThrottlerTest < MiniTest::Test
35
31
  sleep 0.02
36
32
  f.stop
37
33
  assert_in_range 2..4, buffer.size if IS_LINUX
38
- ensure
39
- t.stop
40
34
  end
41
35
 
42
36
  def test_throttler_with_invalid_argument
data/test/test_trace.rb CHANGED
@@ -130,4 +130,91 @@ class TraceTest < MiniTest::Test
130
130
  ensure
131
131
  Thread.backend.trace_proc = nil
132
132
  end
133
+
134
+ def test_event_firehose_with_threaded_receiver
135
+ buffer = []
136
+ this = Fiber.current
137
+ receiver = Thread.new {
138
+ this << :ok
139
+ loop {
140
+ e = receive
141
+ break if e == :stop
142
+ buffer << e
143
+ }
144
+ }
145
+ receive
146
+
147
+ Polyphony::Trace.start_event_firehose { |e| receiver << e }
148
+
149
+ f1 = spin(:f1) do
150
+ receive
151
+ end
152
+
153
+ f1 << :foo
154
+ f1.await
155
+
156
+ Thread.backend.trace_proc = nil
157
+ receiver << :stop
158
+ receiver.await
159
+
160
+ buffer.each { |e| e.delete(:stamp); e.delete(:caller) }
161
+
162
+ main = Fiber.current
163
+ assert_equal(
164
+ [
165
+ { event: :spin, fiber: f1, source_fiber: main },
166
+ { event: :schedule, fiber: f1, value: nil, source_fiber: main },
167
+ { event: :block, fiber: main },
168
+ { event: :unblock, fiber: f1, value: nil },
169
+ { event: :schedule, fiber: f1, value: nil, source_fiber: f1 },
170
+ { event: :block, fiber: f1, },
171
+ { event: :enter_poll },
172
+ { event: :leave_poll },
173
+ { event: :unblock, fiber: f1, value: nil },
174
+ { event: :terminate, fiber: f1, value: :foo },
175
+ { event: :schedule, fiber: main, value: nil, source_fiber: f1 },
176
+ { event: :block, fiber: f1 },
177
+ { event: :unblock, fiber: main, value: nil }
178
+ ], buffer
179
+ )
180
+ ensure
181
+ Thread.backend.trace_proc = nil
182
+ end
183
+
184
+ # def test_event_firehose_with_reentrancy
185
+ # buffer = []
186
+ # Polyphony::Trace.start_event_firehose { |e| buffer << e }
187
+
188
+ # f1 = spin(:f1) do
189
+ # receive
190
+ # end
191
+
192
+ # f1 << :foo
193
+ # f1.await
194
+
195
+ # Thread.backend.trace_proc = nil
196
+ # buffer.each { |e| e.delete(:stamp); e.delete(:caller) }
197
+
198
+ # main = Fiber.current
199
+ # assert_equal(
200
+ # [
201
+ # { event: :spin, fiber: f1, source_fiber: main },
202
+ # { event: :schedule, fiber: f1, value: nil, source_fiber: main },
203
+ # { event: :block, fiber: main },
204
+ # { event: :unblock, fiber: f1, value: nil },
205
+ # { event: :schedule, fiber: f1, value: nil, source_fiber: f1 },
206
+ # { event: :block, fiber: f1, },
207
+ # { event: :enter_poll },
208
+ # { event: :leave_poll },
209
+ # { event: :unblock, fiber: f1, value: nil },
210
+ # { event: :terminate, fiber: f1, value: :foo },
211
+ # { event: :schedule, fiber: main, value: nil, source_fiber: f1 },
212
+ # { event: :block, fiber: f1 },
213
+ # { event: :unblock, fiber: main, value: nil }
214
+ # ], buffer
215
+ # )
216
+ # ensure
217
+ # Thread.backend.trace_proc = nil
218
+ # end
219
+
133
220
  end
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.79'
4
+ version: '0.80'
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: 2022-02-19 00:00:00.000000000 Z
11
+ date: 2022-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: 1.1.4
139
- description:
139
+ description:
140
140
  email: sharon@noteflakes.com
141
141
  executables: []
142
142
  extensions:
@@ -249,6 +249,7 @@ files:
249
249
  - examples/core/trap2.rb
250
250
  - examples/core/using-a-mutex.rb
251
251
  - examples/core/worker-thread.rb
252
+ - examples/core/zlib_stream.rb
252
253
  - examples/io/backticks.rb
253
254
  - examples/io/echo_client.rb
254
255
  - examples/io/echo_client_from_stdin.rb
@@ -358,7 +359,6 @@ files:
358
359
  - lib/polyphony/adapters/readline.rb
359
360
  - lib/polyphony/adapters/redis.rb
360
361
  - lib/polyphony/adapters/sequel.rb
361
- - lib/polyphony/core/channel.rb
362
362
  - lib/polyphony/core/debug.rb
363
363
  - lib/polyphony/core/exceptions.rb
364
364
  - lib/polyphony/core/global_api.rb
@@ -373,6 +373,7 @@ files:
373
373
  - lib/polyphony/extensions/fiber.rb
374
374
  - lib/polyphony/extensions/io.rb
375
375
  - lib/polyphony/extensions/kernel.rb
376
+ - lib/polyphony/extensions/object.rb
376
377
  - lib/polyphony/extensions/openssl.rb
377
378
  - lib/polyphony/extensions/process.rb
378
379
  - lib/polyphony/extensions/socket.rb
@@ -415,7 +416,7 @@ metadata:
415
416
  documentation_uri: https://digital-fabric.github.io/polyphony/
416
417
  homepage_uri: https://digital-fabric.github.io/polyphony/
417
418
  changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
418
- post_install_message:
419
+ post_install_message:
419
420
  rdoc_options:
420
421
  - "--title"
421
422
  - polyphony
@@ -434,8 +435,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
434
435
  - !ruby/object:Gem::Version
435
436
  version: '0'
436
437
  requirements: []
437
- rubygems_version: 3.3.3
438
- signing_key:
438
+ rubygems_version: 3.1.6
439
+ signing_key:
439
440
  specification_version: 4
440
441
  summary: Fine grained concurrency for Ruby
441
442
  test_files: []
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative './exceptions'
4
-
5
- module Polyphony
6
- # Implements a unidirectional communication channel along the lines of Go
7
- # (buffered) channels.
8
- class Channel < Polyphony::Queue
9
- alias_method :receive, :shift
10
-
11
- def close
12
- flush_waiters(Polyphony::MoveOn.new)
13
- end
14
- end
15
- end