polyphony 0.79 → 0.81.1
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/CHANGELOG.md +19 -0
- data/Gemfile.lock +2 -1
- data/examples/core/raw_buffer_test.rb +8 -0
- data/examples/core/zlib_stream.rb +16 -0
- data/ext/polyphony/backend_common.c +2 -1
- data/ext/polyphony/backend_common.h +7 -2
- data/ext/polyphony/backend_io_uring.c +69 -30
- data/ext/polyphony/polyphony.c +8 -0
- data/ext/polyphony/polyphony.h +11 -0
- data/lib/polyphony/adapters/fs.rb +4 -0
- data/lib/polyphony/adapters/process.rb +14 -1
- data/lib/polyphony/adapters/redis.rb +28 -0
- data/lib/polyphony/adapters/sequel.rb +19 -1
- data/lib/polyphony/core/debug.rb +129 -72
- data/lib/polyphony/core/exceptions.rb +21 -6
- data/lib/polyphony/core/global_api.rb +228 -73
- data/lib/polyphony/core/resource_pool.rb +65 -20
- data/lib/polyphony/core/sync.rb +57 -12
- data/lib/polyphony/core/thread_pool.rb +42 -5
- data/lib/polyphony/core/throttler.rb +21 -5
- data/lib/polyphony/core/timer.rb +125 -1
- data/lib/polyphony/extensions/exception.rb +36 -6
- data/lib/polyphony/extensions/fiber.rb +238 -57
- data/lib/polyphony/extensions/io.rb +4 -2
- data/lib/polyphony/extensions/kernel.rb +9 -4
- data/lib/polyphony/extensions/object.rb +8 -0
- data/lib/polyphony/extensions/openssl.rb +3 -1
- data/lib/polyphony/extensions/socket.rb +458 -39
- data/lib/polyphony/extensions/thread.rb +108 -43
- data/lib/polyphony/extensions/timeout.rb +12 -1
- data/lib/polyphony/extensions.rb +1 -0
- data/lib/polyphony/net.rb +66 -7
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +0 -2
- data/test/test_backend.rb +6 -2
- data/test/test_global_api.rb +0 -23
- data/test/test_resource_pool.rb +1 -1
- data/test/test_throttler.rb +0 -6
- data/test/test_trace.rb +87 -0
- metadata +10 -8
- 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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
111
|
-
|
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
|
-
#
|
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
|
data/lib/polyphony/extensions.rb
CHANGED
@@ -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,29 @@ module Polyphony
|
|
28
53
|
end
|
29
54
|
end
|
30
55
|
|
56
|
+
# Sets up ALPN negotiation for the given context. The ALPN handler for the
|
57
|
+
# context will select the first protocol from the list given by the client
|
58
|
+
# that appears in the list of given protocols, according to the specified
|
59
|
+
# order.
|
60
|
+
#
|
61
|
+
# @param context [SSLContext] SSL context
|
62
|
+
# @param protocols [Array] array of supported protocols
|
63
|
+
# @return [void]
|
64
|
+
def setup_alpn(context, protocols)
|
65
|
+
context.alpn_protocols = protocols
|
66
|
+
context.alpn_select_cb = lambda do |peer_protocols|
|
67
|
+
(protocols & peer_protocols).first
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Creates a listening `Socket` instance.
|
74
|
+
#
|
75
|
+
# @param host [String] hostname
|
76
|
+
# @param port [Integer] port number
|
77
|
+
# @param opts [Hash] connection options
|
78
|
+
# @return [Socket] listening socket
|
31
79
|
def listening_socket_from_options(host, port, opts)
|
32
80
|
::Socket.new(:INET, :STREAM).tap do |s|
|
33
81
|
s.reuse_addr if opts[:reuse_addr]
|
@@ -39,6 +87,12 @@ module Polyphony
|
|
39
87
|
end
|
40
88
|
end
|
41
89
|
|
90
|
+
# Wraps the given socket with a SSLSocket and performs a TLS handshake.
|
91
|
+
#
|
92
|
+
# @param socket [Socket] plain socket
|
93
|
+
# @param context [SSLContext, nil] SSL context
|
94
|
+
# @param opts [Hash] connection options
|
95
|
+
# @return [SSLSocket] SSL socket
|
42
96
|
def secure_socket(socket, context, opts)
|
43
97
|
context ||= OpenSSL::SSL::SSLContext.new
|
44
98
|
setup_alpn(context, opts[:alpn_protocols]) if opts[:alpn_protocols]
|
@@ -51,6 +105,11 @@ module Polyphony
|
|
51
105
|
end
|
52
106
|
end
|
53
107
|
|
108
|
+
# Wraps the given socket with an SSLSocket.
|
109
|
+
#
|
110
|
+
# @param socket [Socket] plain socket
|
111
|
+
# @param context [SSLContext] SSL context
|
112
|
+
# @return [SSLSocket] SSL socket
|
54
113
|
def secure_socket_wrapper(socket, context)
|
55
114
|
if context
|
56
115
|
OpenSSL::SSL::SSLSocket.new(socket, context)
|
@@ -59,17 +118,17 @@ module Polyphony
|
|
59
118
|
end
|
60
119
|
end
|
61
120
|
|
121
|
+
# Wraps the given socket with an SSLServer, setting up ALPN from the given
|
122
|
+
# options.
|
123
|
+
#
|
124
|
+
# @param socket [Socket] plain socket
|
125
|
+
# @param context [SSLContext] SSL context
|
126
|
+
# @param opts [Hash] options
|
127
|
+
# @return [SSLServer] SSL socket
|
62
128
|
def secure_server(socket, context, opts)
|
63
129
|
setup_alpn(context, opts[:alpn_protocols]) if opts[:alpn_protocols]
|
64
130
|
OpenSSL::SSL::SSLServer.new(socket, context)
|
65
131
|
end
|
66
|
-
|
67
|
-
def setup_alpn(context, protocols)
|
68
|
-
context.alpn_protocols = protocols
|
69
|
-
context.alpn_select_cb = lambda do |peer_protocols|
|
70
|
-
(protocols & peer_protocols).first
|
71
|
-
end
|
72
|
-
end
|
73
132
|
end
|
74
133
|
end
|
75
134
|
end
|
data/lib/polyphony/version.rb
CHANGED
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.
|
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.
|
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
|
data/test/test_global_api.rb
CHANGED
@@ -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_resource_pool.rb
CHANGED
data/test/test_throttler.rb
CHANGED
@@ -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:
|
4
|
+
version: 0.81.1
|
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-
|
11
|
+
date: 2022-03-03 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:
|
@@ -232,6 +232,7 @@ files:
|
|
232
232
|
- examples/core/nested.rb
|
233
233
|
- examples/core/pingpong.rb
|
234
234
|
- examples/core/queue.rb
|
235
|
+
- examples/core/raw_buffer_test.rb
|
235
236
|
- examples/core/recurrent-timer.rb
|
236
237
|
- examples/core/resource_delegate.rb
|
237
238
|
- examples/core/ring.rb
|
@@ -249,6 +250,7 @@ files:
|
|
249
250
|
- examples/core/trap2.rb
|
250
251
|
- examples/core/using-a-mutex.rb
|
251
252
|
- examples/core/worker-thread.rb
|
253
|
+
- examples/core/zlib_stream.rb
|
252
254
|
- examples/io/backticks.rb
|
253
255
|
- examples/io/echo_client.rb
|
254
256
|
- examples/io/echo_client_from_stdin.rb
|
@@ -358,7 +360,6 @@ files:
|
|
358
360
|
- lib/polyphony/adapters/readline.rb
|
359
361
|
- lib/polyphony/adapters/redis.rb
|
360
362
|
- lib/polyphony/adapters/sequel.rb
|
361
|
-
- lib/polyphony/core/channel.rb
|
362
363
|
- lib/polyphony/core/debug.rb
|
363
364
|
- lib/polyphony/core/exceptions.rb
|
364
365
|
- lib/polyphony/core/global_api.rb
|
@@ -373,6 +374,7 @@ files:
|
|
373
374
|
- lib/polyphony/extensions/fiber.rb
|
374
375
|
- lib/polyphony/extensions/io.rb
|
375
376
|
- lib/polyphony/extensions/kernel.rb
|
377
|
+
- lib/polyphony/extensions/object.rb
|
376
378
|
- lib/polyphony/extensions/openssl.rb
|
377
379
|
- lib/polyphony/extensions/process.rb
|
378
380
|
- lib/polyphony/extensions/socket.rb
|
@@ -415,7 +417,7 @@ metadata:
|
|
415
417
|
documentation_uri: https://digital-fabric.github.io/polyphony/
|
416
418
|
homepage_uri: https://digital-fabric.github.io/polyphony/
|
417
419
|
changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
|
418
|
-
post_install_message:
|
420
|
+
post_install_message:
|
419
421
|
rdoc_options:
|
420
422
|
- "--title"
|
421
423
|
- polyphony
|
@@ -434,8 +436,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
434
436
|
- !ruby/object:Gem::Version
|
435
437
|
version: '0'
|
436
438
|
requirements: []
|
437
|
-
rubygems_version: 3.
|
438
|
-
signing_key:
|
439
|
+
rubygems_version: 3.1.6
|
440
|
+
signing_key:
|
439
441
|
specification_version: 4
|
440
442
|
summary: Fine grained concurrency for Ruby
|
441
443
|
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
|