polyphony 0.69 → 0.73
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/.github/FUNDING.yml +1 -0
- data/.github/workflows/test.yml +2 -2
- data/.gitignore +3 -1
- data/CHANGELOG.md +33 -4
- data/Gemfile.lock +2 -2
- data/TODO.md +1 -24
- data/bin/pdbg +1 -1
- data/bin/polyphony-debug +0 -0
- data/bin/stress.rb +0 -0
- data/bin/test +0 -0
- data/docs/_user-guide/all-about-timers.md +1 -1
- data/docs/api-reference/exception.md +5 -1
- data/docs/api-reference/fiber.md +2 -2
- data/docs/faq.md +1 -1
- data/docs/getting-started/overview.md +8 -8
- data/docs/getting-started/tutorial.md +3 -3
- data/docs/main-concepts/concurrency.md +1 -1
- data/docs/main-concepts/extending.md +3 -3
- data/docs/main-concepts/fiber-scheduling.md +1 -1
- data/examples/core/calc.rb +37 -0
- data/examples/core/calc_with_restart.rb +40 -0
- data/examples/core/calc_with_supervise.rb +37 -0
- data/examples/core/message_based_supervision.rb +1 -1
- data/examples/core/ring.rb +29 -0
- data/examples/io/rack_server.rb +1 -1
- data/examples/io/tunnel.rb +1 -1
- data/examples/performance/fiber_transfer.rb +1 -1
- data/examples/performance/line_splitting.rb +1 -1
- data/examples/performance/thread-vs-fiber/compare.rb +1 -1
- data/ext/polyphony/backend_common.c +31 -7
- data/ext/polyphony/backend_common.h +2 -1
- data/ext/polyphony/backend_io_uring.c +57 -67
- data/ext/polyphony/backend_io_uring_context.c +1 -1
- data/ext/polyphony/backend_io_uring_context.h +1 -1
- data/ext/polyphony/backend_libev.c +38 -30
- data/ext/polyphony/extconf.rb +25 -13
- data/ext/polyphony/polyphony.h +5 -1
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue_ring_buffer.c +3 -2
- data/ext/polyphony/thread.c +1 -1
- data/lib/polyphony/adapters/irb.rb +11 -1
- data/lib/polyphony/{extensions → core}/debug.rb +0 -0
- data/lib/polyphony/core/global_api.rb +3 -6
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/debugger.rb +3 -3
- data/lib/polyphony/extensions/exception.rb +45 -0
- data/lib/polyphony/extensions/fiber.rb +30 -16
- data/lib/polyphony/extensions/io.rb +2 -2
- data/lib/polyphony/extensions/{core.rb → kernel.rb} +0 -73
- data/lib/polyphony/extensions/openssl.rb +20 -5
- data/lib/polyphony/extensions/process.rb +19 -0
- data/lib/polyphony/extensions/socket.rb +3 -4
- data/lib/polyphony/extensions/timeout.rb +10 -0
- data/lib/polyphony/extensions.rb +9 -0
- data/lib/polyphony/net.rb +0 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony.rb +2 -5
- data/polyphony.gemspec +1 -1
- data/test/coverage.rb +2 -2
- data/test/stress.rb +1 -1
- data/test/test_backend.rb +12 -12
- data/test/test_event.rb +1 -1
- data/test/test_ext.rb +1 -1
- data/test/test_fiber.rb +52 -12
- data/test/test_global_api.rb +16 -4
- data/test/test_io.rb +3 -3
- data/test/test_process_supervision.rb +39 -10
- data/test/test_queue.rb +6 -6
- data/test/test_signal.rb +20 -1
- data/test/test_socket.rb +12 -10
- data/test/test_supervise.rb +249 -81
- data/test/test_sync.rb +2 -2
- data/test/test_thread.rb +22 -2
- data/test/test_thread_pool.rb +1 -1
- data/test/test_throttler.rb +1 -1
- data/test/test_timer.rb +2 -2
- data/test/test_trace.rb +1 -1
- metadata +18 -9
data/test/test_supervise.rb
CHANGED
@@ -3,12 +3,6 @@
|
|
3
3
|
require_relative 'helper'
|
4
4
|
|
5
5
|
class SuperviseTest < MiniTest::Test
|
6
|
-
def test_supervise_with_no_arguments
|
7
|
-
assert_raises(RuntimeError) do
|
8
|
-
supervise
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
6
|
def test_supervise_with_block
|
13
7
|
buffer = []
|
14
8
|
f1 = spin(:f1) { receive }
|
@@ -26,79 +20,253 @@ class SuperviseTest < MiniTest::Test
|
|
26
20
|
assert_equal [[f1, 'foo'], [f2, 'bar']], buffer
|
27
21
|
end
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
23
|
+
def test_supervise_with_on_done
|
24
|
+
buffer = []
|
25
|
+
f1 = spin(:f1) { receive }
|
26
|
+
f2 = spin(:f2) { receive }
|
27
|
+
supervisor = spin(:supervisor) do
|
28
|
+
supervise(f1, f2, on_done: ->(*args) { buffer << args })
|
29
|
+
end
|
30
|
+
|
31
|
+
snooze
|
32
|
+
f1 << 'foo'
|
33
|
+
f1.await
|
34
|
+
10.times { snooze }
|
35
|
+
assert_equal [[f1, 'foo']], buffer
|
36
|
+
|
37
|
+
f2 << 'bar'
|
38
|
+
f2.await
|
39
|
+
assert_equal [[f1, 'foo'], [f2, 'bar']], buffer
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_supervise_with_on_error
|
43
|
+
buffer = []
|
44
|
+
f1 = spin(:f1) { receive }
|
45
|
+
f2 = spin(:f2) { receive }
|
46
|
+
supervisor = spin(:supervisor) do
|
47
|
+
supervise(f1, f2, on_error: ->(*args) { buffer << args })
|
48
|
+
end
|
49
|
+
|
50
|
+
snooze
|
51
|
+
f1 << 'foo'
|
52
|
+
f1.await
|
53
|
+
10.times { snooze }
|
54
|
+
assert_equal [], buffer
|
55
|
+
|
56
|
+
e = RuntimeError.new('blah')
|
57
|
+
f2.raise(e)
|
58
|
+
3.times { snooze }
|
59
|
+
assert_equal [[f2, e]], buffer
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_supervise_with_manual_restart
|
63
|
+
buffer = []
|
64
|
+
f1 = spin(:f1) { receive }
|
65
|
+
supervisor = spin(:supervisor) do
|
66
|
+
supervise(f1) do |f, r|
|
67
|
+
buffer << [f, r]
|
68
|
+
f.restart
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
snooze
|
73
|
+
f1 << 'foo'
|
74
|
+
f1.await
|
75
|
+
snooze
|
76
|
+
assert_equal [[f1, 'foo']], buffer
|
77
|
+
|
78
|
+
10.times { snooze }
|
79
|
+
|
80
|
+
assert_equal 1, supervisor.children.size
|
81
|
+
f2 = supervisor.children.first
|
82
|
+
assert f1 != f2
|
83
|
+
assert_equal :f1, f2.tag
|
84
|
+
assert_equal supervisor, f2.parent
|
85
|
+
|
86
|
+
e = RuntimeError.new('bar')
|
87
|
+
f2.raise(e)
|
88
|
+
f2.await rescue nil
|
89
|
+
3.times { snooze }
|
90
|
+
assert_equal [[f1, 'foo'], [f2, e]], buffer
|
91
|
+
|
92
|
+
assert_equal 1, supervisor.children.size
|
93
|
+
f3 = supervisor.children.first
|
94
|
+
assert f2 != f3
|
95
|
+
assert f1 != f3
|
96
|
+
assert_equal :f1, f3.tag
|
97
|
+
assert_equal supervisor, f3.parent
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_supervise_with_restart_always
|
101
|
+
buffer = []
|
102
|
+
f1 = spin(:f1) do
|
103
|
+
buffer << receive
|
104
|
+
rescue => e
|
105
|
+
buffer << e
|
106
|
+
e
|
107
|
+
end
|
108
|
+
supervisor = spin(:supervisor) { supervise(f1, restart: :always) }
|
109
|
+
|
110
|
+
snooze
|
111
|
+
f1 << 'foo'
|
112
|
+
f1.await
|
113
|
+
snooze
|
114
|
+
assert_equal ['foo'], buffer
|
115
|
+
|
116
|
+
10.times { snooze }
|
117
|
+
|
118
|
+
assert_equal 1, supervisor.children.size
|
119
|
+
f2 = supervisor.children.first
|
120
|
+
assert f1 != f2
|
121
|
+
assert_equal :f1, f2.tag
|
122
|
+
assert_equal supervisor, f2.parent
|
123
|
+
|
124
|
+
e = RuntimeError.new('bar')
|
125
|
+
f2.raise(e)
|
126
|
+
f2.await rescue nil
|
127
|
+
3.times { snooze }
|
128
|
+
assert_equal ['foo', e], buffer
|
129
|
+
|
130
|
+
assert_equal 1, supervisor.children.size
|
131
|
+
f3 = supervisor.children.first
|
132
|
+
assert f2 != f3
|
133
|
+
assert f1 != f3
|
134
|
+
assert_equal :f1, f3.tag
|
135
|
+
assert_equal supervisor, f3.parent
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_supervise_with_restart_true
|
139
|
+
buffer = []
|
140
|
+
f1 = spin(:f1) do
|
141
|
+
buffer << receive
|
142
|
+
rescue => e
|
143
|
+
buffer << e
|
144
|
+
e
|
145
|
+
end
|
146
|
+
supervisor = spin(:supervisor) { supervise(f1, restart: true) }
|
147
|
+
|
148
|
+
snooze
|
149
|
+
f1 << 'foo'
|
150
|
+
f1.await
|
151
|
+
snooze
|
152
|
+
assert_equal ['foo'], buffer
|
153
|
+
|
154
|
+
10.times { snooze }
|
155
|
+
|
156
|
+
assert_equal 1, supervisor.children.size
|
157
|
+
f2 = supervisor.children.first
|
158
|
+
assert f1 != f2
|
159
|
+
assert_equal :f1, f2.tag
|
160
|
+
assert_equal supervisor, f2.parent
|
161
|
+
|
162
|
+
e = RuntimeError.new('bar')
|
163
|
+
f2.raise(e)
|
164
|
+
f2.await rescue nil
|
165
|
+
3.times { snooze }
|
166
|
+
assert_equal ['foo', e], buffer
|
167
|
+
|
168
|
+
assert_equal 1, supervisor.children.size
|
169
|
+
f3 = supervisor.children.first
|
170
|
+
assert f2 != f3
|
171
|
+
assert f1 != f3
|
172
|
+
assert_equal :f1, f3.tag
|
173
|
+
assert_equal supervisor, f3.parent
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_supervise_with_restart_on_error
|
177
|
+
buffer = []
|
178
|
+
f1 = spin(:f1) do
|
179
|
+
buffer << receive
|
180
|
+
rescue => e
|
181
|
+
buffer << e
|
182
|
+
e
|
183
|
+
end
|
184
|
+
supervisor = spin(:supervisor) { supervise(f1, restart: :on_error) }
|
185
|
+
|
186
|
+
snooze
|
187
|
+
e = RuntimeError.new('bar')
|
188
|
+
f1.raise(e)
|
189
|
+
f1.await rescue nil
|
190
|
+
snooze
|
191
|
+
assert_equal [e], buffer
|
192
|
+
|
193
|
+
10.times { snooze }
|
194
|
+
|
195
|
+
assert_equal 1, supervisor.children.size
|
196
|
+
f2 = supervisor.children.first
|
197
|
+
assert f1 != f2
|
198
|
+
assert_equal :f1, f2.tag
|
199
|
+
assert_equal supervisor, f2.parent
|
200
|
+
|
201
|
+
f2 << 'foo'
|
202
|
+
f2.await rescue nil
|
203
|
+
3.times { snooze }
|
204
|
+
assert_equal [e, 'foo'], buffer
|
205
|
+
|
206
|
+
assert_equal 0, supervisor.children.size
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_supervise_terminate
|
210
|
+
buffer = []
|
211
|
+
f1 = spin(:f1) do
|
212
|
+
buffer << receive
|
213
|
+
rescue => e
|
214
|
+
buffer << e
|
215
|
+
e
|
216
|
+
end
|
217
|
+
supervisor = spin(:supervisor) { supervise(f1, restart: :on_error) }
|
218
|
+
|
219
|
+
sleep 0.05
|
220
|
+
supervisor.terminate
|
221
|
+
supervisor.await
|
222
|
+
|
223
|
+
assert_equal [], buffer
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_supervise_without_explicit_fibers
|
227
|
+
buffer = []
|
228
|
+
first = nil
|
229
|
+
supervisor = spin do
|
230
|
+
3.times do |i|
|
231
|
+
f = spin do
|
232
|
+
first = Fiber.current if i == 0
|
233
|
+
receive
|
234
|
+
buffer << i
|
235
|
+
end
|
236
|
+
end
|
237
|
+
Fiber.current.parent << :ok
|
238
|
+
supervise(restart: :always)
|
239
|
+
end
|
240
|
+
msg = receive
|
241
|
+
assert_equal :ok, msg
|
242
|
+
assert_equal 3, supervisor.children.size
|
243
|
+
|
244
|
+
sleep 0.1
|
245
|
+
assert_equal [], buffer
|
246
|
+
|
247
|
+
old_first = first
|
248
|
+
first << :foo
|
249
|
+
first = nil
|
250
|
+
snooze
|
251
|
+
assert_equal [0], buffer
|
252
|
+
|
253
|
+
snooze
|
254
|
+
assert_equal 3, supervisor.children.size
|
255
|
+
snooze
|
256
|
+
assert first
|
257
|
+
assert first != old_first
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_supervise_with_added_fibers
|
261
|
+
buffer = []
|
262
|
+
supervisor = spin do
|
263
|
+
supervise { |f, r| buffer << [f, r] }
|
264
|
+
end
|
265
|
+
snooze
|
266
|
+
f1 = supervisor.spin { snooze; :foo }
|
267
|
+
f2 = supervisor.spin { snooze; :bar }
|
268
|
+
Fiber.await(f1, f2)
|
269
|
+
snooze
|
270
|
+
assert_equal [[f1, :foo], [f2, :bar]], buffer
|
271
|
+
end
|
104
272
|
end
|
data/test/test_sync.rb
CHANGED
data/test/test_thread.rb
CHANGED
@@ -180,7 +180,7 @@ class ThreadTest < MiniTest::Test
|
|
180
180
|
assert_equal count, GC.count
|
181
181
|
sleep 0.05
|
182
182
|
assert_equal count, GC.count
|
183
|
-
|
183
|
+
|
184
184
|
return unless IS_LINUX
|
185
185
|
|
186
186
|
# The idle tasks are ran at most once per fiber switch, before the backend
|
@@ -207,7 +207,7 @@ class ThreadTest < MiniTest::Test
|
|
207
207
|
counter = 0
|
208
208
|
|
209
209
|
Thread.current.on_idle { counter += 1 }
|
210
|
-
|
210
|
+
|
211
211
|
3.times { snooze }
|
212
212
|
assert_equal 0, counter
|
213
213
|
|
@@ -220,4 +220,24 @@ class ThreadTest < MiniTest::Test
|
|
220
220
|
3.times { snooze }
|
221
221
|
assert_equal 2, counter
|
222
222
|
end
|
223
|
+
|
224
|
+
def test_cross_thread_receive
|
225
|
+
buf = []
|
226
|
+
f = Fiber.current
|
227
|
+
t = Thread.new do
|
228
|
+
f << true
|
229
|
+
while (msg = receive)
|
230
|
+
buf << msg
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
receive # wait for thread to be ready
|
235
|
+
t << 1
|
236
|
+
t << 2
|
237
|
+
t << 3
|
238
|
+
t << nil
|
239
|
+
|
240
|
+
t.join
|
241
|
+
assert_equal [1, 2, 3], buf
|
242
|
+
end
|
223
243
|
end
|
data/test/test_thread_pool.rb
CHANGED
data/test/test_throttler.rb
CHANGED
data/test/test_timer.rb
CHANGED
@@ -137,11 +137,11 @@ class TimerMiscTest < MiniTest::Test
|
|
137
137
|
@timer = Polyphony::Timer.new(resolution: 0.001)
|
138
138
|
sleep 0
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
def teardown
|
142
142
|
@timer.stop
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def test_timer_after
|
146
146
|
buffer = []
|
147
147
|
f = @timer.after(0.01) { buffer << 2 }
|
data/test/test_trace.rb
CHANGED
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.
|
4
|
+
version: '0.73'
|
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: 2021-
|
11
|
+
date: 2021-12-16 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:
|
@@ -144,6 +144,7 @@ extensions:
|
|
144
144
|
extra_rdoc_files:
|
145
145
|
- README.md
|
146
146
|
files:
|
147
|
+
- ".github/FUNDING.yml"
|
147
148
|
- ".github/workflows/test.yml"
|
148
149
|
- ".gitignore"
|
149
150
|
- ".gitmodules"
|
@@ -215,6 +216,9 @@ files:
|
|
215
216
|
- examples/adapters/sequel_mysql_pool.rb
|
216
217
|
- examples/adapters/sequel_pg.rb
|
217
218
|
- examples/core/await.rb
|
219
|
+
- examples/core/calc.rb
|
220
|
+
- examples/core/calc_with_restart.rb
|
221
|
+
- examples/core/calc_with_supervise.rb
|
218
222
|
- examples/core/channels.rb
|
219
223
|
- examples/core/deferring-an-operation.rb
|
220
224
|
- examples/core/enumerable.rb
|
@@ -229,6 +233,7 @@ files:
|
|
229
233
|
- examples/core/queue.rb
|
230
234
|
- examples/core/recurrent-timer.rb
|
231
235
|
- examples/core/resource_delegate.rb
|
236
|
+
- examples/core/ring.rb
|
232
237
|
- examples/core/spin.rb
|
233
238
|
- examples/core/spin_error_backtrace.rb
|
234
239
|
- examples/core/supervise-process.rb
|
@@ -350,6 +355,7 @@ files:
|
|
350
355
|
- lib/polyphony/adapters/redis.rb
|
351
356
|
- lib/polyphony/adapters/sequel.rb
|
352
357
|
- lib/polyphony/core/channel.rb
|
358
|
+
- lib/polyphony/core/debug.rb
|
353
359
|
- lib/polyphony/core/exceptions.rb
|
354
360
|
- lib/polyphony/core/global_api.rb
|
355
361
|
- lib/polyphony/core/resource_pool.rb
|
@@ -358,13 +364,16 @@ files:
|
|
358
364
|
- lib/polyphony/core/throttler.rb
|
359
365
|
- lib/polyphony/core/timer.rb
|
360
366
|
- lib/polyphony/debugger.rb
|
361
|
-
- lib/polyphony/extensions
|
362
|
-
- lib/polyphony/extensions/
|
367
|
+
- lib/polyphony/extensions.rb
|
368
|
+
- lib/polyphony/extensions/exception.rb
|
363
369
|
- lib/polyphony/extensions/fiber.rb
|
364
370
|
- lib/polyphony/extensions/io.rb
|
371
|
+
- lib/polyphony/extensions/kernel.rb
|
365
372
|
- lib/polyphony/extensions/openssl.rb
|
373
|
+
- lib/polyphony/extensions/process.rb
|
366
374
|
- lib/polyphony/extensions/socket.rb
|
367
375
|
- lib/polyphony/extensions/thread.rb
|
376
|
+
- lib/polyphony/extensions/timeout.rb
|
368
377
|
- lib/polyphony/net.rb
|
369
378
|
- lib/polyphony/version.rb
|
370
379
|
- polyphony.gemspec
|
@@ -402,7 +411,7 @@ metadata:
|
|
402
411
|
documentation_uri: https://digital-fabric.github.io/polyphony/
|
403
412
|
homepage_uri: https://digital-fabric.github.io/polyphony/
|
404
413
|
changelog_uri: https://github.com/digital-fabric/polyphony/blob/master/CHANGELOG.md
|
405
|
-
post_install_message:
|
414
|
+
post_install_message:
|
406
415
|
rdoc_options:
|
407
416
|
- "--title"
|
408
417
|
- polyphony
|
@@ -421,8 +430,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
421
430
|
- !ruby/object:Gem::Version
|
422
431
|
version: '0'
|
423
432
|
requirements: []
|
424
|
-
rubygems_version: 3.
|
425
|
-
signing_key:
|
433
|
+
rubygems_version: 3.3.0.dev
|
434
|
+
signing_key:
|
426
435
|
specification_version: 4
|
427
436
|
summary: Fine grained concurrency for Ruby
|
428
437
|
test_files: []
|