polyphony 0.68 → 0.72
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/CHANGELOG.md +32 -5
- 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/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/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 +24 -6
- data/ext/polyphony/backend_common.h +1 -0
- data/ext/polyphony/backend_io_uring.c +27 -40
- 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 +13 -11
- data/ext/polyphony/extconf.rb +24 -13
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue_ring_buffer.c +3 -2
- data/lib/polyphony/adapters/irb.rb +11 -1
- data/lib/polyphony/core/global_api.rb +3 -3
- data/lib/polyphony/core/timer.rb +2 -2
- data/lib/polyphony/debugger.rb +3 -3
- data/lib/polyphony/extensions/fiber.rb +30 -15
- data/lib/polyphony/extensions/io.rb +3 -3
- data/lib/polyphony/extensions/openssl.rb +21 -6
- data/lib/polyphony/extensions/socket.rb +4 -5
- data/lib/polyphony/net.rb +0 -1
- data/lib/polyphony/version.rb +1 -1
- 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 +2 -3
- data/test/test_io.rb +3 -3
- data/test/test_process_supervision.rb +38 -9
- data/test/test_queue.rb +6 -6
- 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 +7 -3
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.72'
|
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
|
+
date: 2021-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -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
|
@@ -421,7 +425,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
421
425
|
- !ruby/object:Gem::Version
|
422
426
|
version: '0'
|
423
427
|
requirements: []
|
424
|
-
rubygems_version: 3.1.
|
428
|
+
rubygems_version: 3.1.2
|
425
429
|
signing_key:
|
426
430
|
specification_version: 4
|
427
431
|
summary: Fine grained concurrency for Ruby
|