polyphony 0.32 → 0.33
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/workflows/test.yml +20 -0
- data/.rubocop.yml +14 -1
- data/CHANGELOG.md +10 -2
- data/Gemfile.lock +1 -1
- data/README.md +4 -0
- data/TODO.md +116 -1
- data/docs/_sass/custom/custom.scss +4 -0
- data/docs/_sass/overrides.scss +4 -6
- data/docs/getting-started/installing.md +2 -2
- data/docs/getting-started/tutorial.md +17 -15
- data/docs/index.md +18 -23
- data/docs/main-concepts/concurrency.md +1 -1
- data/ext/gyro/async.c +27 -0
- data/ext/gyro/gyro.h +1 -0
- data/ext/gyro/queue.c +10 -9
- data/ext/gyro/selector.c +3 -5
- data/ext/gyro/thread.c +6 -17
- data/lib/polyphony.rb +1 -0
- data/lib/polyphony/core/exceptions.rb +4 -1
- data/lib/polyphony/core/global_api.rb +4 -0
- data/lib/polyphony/extensions/core.rb +4 -3
- data/lib/polyphony/extensions/fiber.rb +72 -11
- data/lib/polyphony/extensions/thread.rb +20 -7
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +2 -2
- data/test/stress.rb +20 -0
- data/test/test_fiber.rb +158 -4
- data/test/test_global_api.rb +21 -14
- data/test/test_kernel.rb +23 -0
- data/test/test_signal.rb +1 -1
- data/test/test_thread.rb +4 -3
- data/test/test_thread_pool.rb +2 -2
- metadata +6 -4
data/test/test_fiber.rb
CHANGED
@@ -168,6 +168,7 @@ class FiberTest < MiniTest::Test
|
|
168
168
|
end
|
169
169
|
assert_kind_of Hash, result
|
170
170
|
assert_kind_of RuntimeError, result[:error]
|
171
|
+
assert_equal f, result[:error].source_fiber
|
171
172
|
ensure
|
172
173
|
f&.stop
|
173
174
|
end
|
@@ -180,7 +181,7 @@ class FiberTest < MiniTest::Test
|
|
180
181
|
2.times { snooze }
|
181
182
|
result << 2
|
182
183
|
end
|
183
|
-
spin { f.raise }
|
184
|
+
f2 = spin { f.raise }
|
184
185
|
assert_equal 0, result.size
|
185
186
|
begin
|
186
187
|
f.await
|
@@ -190,6 +191,7 @@ class FiberTest < MiniTest::Test
|
|
190
191
|
assert_equal 1, result.size
|
191
192
|
assert_equal 1, result[0]
|
192
193
|
assert_kind_of RuntimeError, error
|
194
|
+
assert_equal f, error.source_fiber
|
193
195
|
ensure
|
194
196
|
f&.stop
|
195
197
|
end
|
@@ -250,7 +252,7 @@ class FiberTest < MiniTest::Test
|
|
250
252
|
2.times { snooze }
|
251
253
|
result << 2
|
252
254
|
end
|
253
|
-
spin { f.raise 'foo' }
|
255
|
+
f2 = spin { f.raise 'foo' }
|
254
256
|
assert_equal 0, result.size
|
255
257
|
begin
|
256
258
|
f.await
|
@@ -261,6 +263,7 @@ class FiberTest < MiniTest::Test
|
|
261
263
|
assert_equal 1, result[0]
|
262
264
|
assert_kind_of RuntimeError, error
|
263
265
|
assert_equal 'foo', error.message
|
266
|
+
assert_equal f, error.source_fiber
|
264
267
|
ensure
|
265
268
|
f&.stop
|
266
269
|
end
|
@@ -663,7 +666,6 @@ class FiberTest < MiniTest::Test
|
|
663
666
|
o.close
|
664
667
|
end
|
665
668
|
snooze
|
666
|
-
ensure
|
667
669
|
end
|
668
670
|
o.close
|
669
671
|
Gyro::Child.new(pid).await
|
@@ -827,6 +829,7 @@ class FiberControlTest < MiniTest::Test
|
|
827
829
|
end
|
828
830
|
assert_kind_of RuntimeError, error
|
829
831
|
assert_equal 'foo', error.message
|
832
|
+
assert_equal f1, error.source_fiber
|
830
833
|
|
831
834
|
assert_equal :dead, f1.state
|
832
835
|
assert_equal :dead, f2.state
|
@@ -863,6 +866,7 @@ class FiberControlTest < MiniTest::Test
|
|
863
866
|
|
864
867
|
assert_kind_of RuntimeError, result
|
865
868
|
assert_equal 'foo', result.message
|
869
|
+
assert_equal f1, result.source_fiber
|
866
870
|
assert_equal :dead, f1.state
|
867
871
|
assert_equal :dead, f2.state
|
868
872
|
end
|
@@ -874,4 +878,154 @@ class FiberControlTest < MiniTest::Test
|
|
874
878
|
result = Fiber.select(f1, f2)
|
875
879
|
assert_equal [f2, :baz], result
|
876
880
|
end
|
877
|
-
end
|
881
|
+
end
|
882
|
+
|
883
|
+
class SupervisionTest < MiniTest::Test
|
884
|
+
def test_exception_during_termination
|
885
|
+
f2 = nil
|
886
|
+
f = spin do
|
887
|
+
f2 = spin do
|
888
|
+
sleep
|
889
|
+
rescue Polyphony::Terminate
|
890
|
+
raise 'foo'
|
891
|
+
end
|
892
|
+
sleep
|
893
|
+
end
|
894
|
+
|
895
|
+
sleep 0.01
|
896
|
+
e = nil
|
897
|
+
begin
|
898
|
+
f.terminate
|
899
|
+
f.await
|
900
|
+
rescue => e
|
901
|
+
end
|
902
|
+
|
903
|
+
assert_kind_of RuntimeError, e
|
904
|
+
assert_equal 'foo', e.message
|
905
|
+
assert_equal f2, e.source_fiber
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
class RestartTest < MiniTest::Test
|
910
|
+
def test_restart
|
911
|
+
buffer = []
|
912
|
+
f = spin {
|
913
|
+
buffer << 1
|
914
|
+
receive
|
915
|
+
buffer << 2
|
916
|
+
}
|
917
|
+
snooze
|
918
|
+
assert_equal [1], buffer
|
919
|
+
f2 = f.restart
|
920
|
+
assert_equal f2, f
|
921
|
+
assert_equal [1], buffer
|
922
|
+
snooze
|
923
|
+
assert_equal [1, 1], buffer
|
924
|
+
|
925
|
+
f << 'foo'
|
926
|
+
sleep 0.1
|
927
|
+
assert_equal [1, 1, 2], buffer
|
928
|
+
end
|
929
|
+
|
930
|
+
def test_restart_after_finalization
|
931
|
+
buffer = []
|
932
|
+
parent = spin {
|
933
|
+
sleep
|
934
|
+
}
|
935
|
+
|
936
|
+
f = parent.spin { |v|
|
937
|
+
buffer << Fiber.current
|
938
|
+
buffer << v
|
939
|
+
buffer << receive
|
940
|
+
buffer << :done
|
941
|
+
}
|
942
|
+
f.schedule('foo')
|
943
|
+
f << 'bar'
|
944
|
+
snooze
|
945
|
+
f.await
|
946
|
+
|
947
|
+
assert_equal [f, 'foo', 'bar', :done], buffer
|
948
|
+
assert_equal parent, f.parent
|
949
|
+
|
950
|
+
f2 = f.restart('baz')
|
951
|
+
assert f2 != f
|
952
|
+
assert_equal parent, f2.parent
|
953
|
+
|
954
|
+
f2 << 42
|
955
|
+
f2.await
|
956
|
+
assert_equal [f, 'foo', 'bar', :done, f2, 'baz', 42, :done], buffer
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
class SuperviseTest < MiniTest::Test
|
961
|
+
def test_supervise
|
962
|
+
p = spin { supervise }
|
963
|
+
snooze
|
964
|
+
f1 = p.spin { receive }
|
965
|
+
f2 = p.spin { receive }
|
966
|
+
|
967
|
+
snooze
|
968
|
+
assert_equal p.state, :waiting
|
969
|
+
f1 << 'foo'
|
970
|
+
f1.await
|
971
|
+
snooze
|
972
|
+
|
973
|
+
assert_equal :waiting, p.state
|
974
|
+
assert_equal :waiting, f2.state
|
975
|
+
|
976
|
+
f2 << 'bar'
|
977
|
+
f2.await
|
978
|
+
snooze
|
979
|
+
|
980
|
+
assert_equal :waiting, p.state
|
981
|
+
end
|
982
|
+
|
983
|
+
def test_supervise_with_restart
|
984
|
+
parent = spin { supervise(on_error: :restart) }
|
985
|
+
snooze
|
986
|
+
|
987
|
+
buffer = []
|
988
|
+
f1 = parent.spin do
|
989
|
+
buffer << 'f1'
|
990
|
+
buffer << receive
|
991
|
+
end
|
992
|
+
|
993
|
+
snooze
|
994
|
+
assert_equal ['f1'], buffer
|
995
|
+
|
996
|
+
f1.raise 'foo'
|
997
|
+
|
998
|
+
3.times { snooze }
|
999
|
+
|
1000
|
+
assert_equal ['f1', 'f1'], buffer
|
1001
|
+
assert_equal :dead, f1.state
|
1002
|
+
|
1003
|
+
# f1 should have been restarted by supervisor
|
1004
|
+
f1 = parent.children.first
|
1005
|
+
assert_kind_of Fiber, f1
|
1006
|
+
f1 << 'foo'
|
1007
|
+
|
1008
|
+
f1.await
|
1009
|
+
3.times { snooze }
|
1010
|
+
|
1011
|
+
assert_equal ['f1', 'f1', 'foo'], buffer
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
def test_supervise_with_block
|
1015
|
+
failed = []
|
1016
|
+
p = spin do
|
1017
|
+
supervise(on_error: :restart) { |f, e| failed << [f, e] }
|
1018
|
+
end
|
1019
|
+
snooze
|
1020
|
+
f1 = p.spin { receive }
|
1021
|
+
snooze
|
1022
|
+
|
1023
|
+
f1.raise 'foo'
|
1024
|
+
3.times { snooze }
|
1025
|
+
|
1026
|
+
assert_equal 1, failed.size
|
1027
|
+
assert_equal f1, failed.first[0]
|
1028
|
+
assert_kind_of RuntimeError, failed.first[1]
|
1029
|
+
assert_equal 'foo', failed.first[1].message
|
1030
|
+
end
|
1031
|
+
end
|
data/test/test_global_api.rb
CHANGED
@@ -40,6 +40,18 @@ class SpinTest < MiniTest::Test
|
|
40
40
|
suspend
|
41
41
|
assert_nil fiber.result
|
42
42
|
end
|
43
|
+
|
44
|
+
def test_spin_without_tag
|
45
|
+
f = spin { }
|
46
|
+
assert_kind_of Fiber, f
|
47
|
+
assert_nil f.tag
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_spin_with_tag
|
51
|
+
f = spin(:foo) { }
|
52
|
+
assert_kind_of Fiber, f
|
53
|
+
assert_equal :foo, f.tag
|
54
|
+
end
|
43
55
|
end
|
44
56
|
|
45
57
|
class ExceptionTest < MiniTest::Test
|
@@ -111,20 +123,6 @@ class MoveOnAfterTest < MiniTest::Test
|
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
114
|
-
class SpinTest < MiniTest::Test
|
115
|
-
def test_spin_without_tag
|
116
|
-
f = spin { }
|
117
|
-
assert_kind_of Fiber, f
|
118
|
-
assert_nil f.tag
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_spin_with_tag
|
122
|
-
f = spin(:foo) { }
|
123
|
-
assert_kind_of Fiber, f
|
124
|
-
assert_equal :foo, f.tag
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
126
|
class SpinLoopTest < MiniTest::Test
|
129
127
|
def test_spin_loop
|
130
128
|
buffer = []
|
@@ -195,6 +193,15 @@ class ThrottledLoopTest < MiniTest::Test
|
|
195
193
|
end
|
196
194
|
|
197
195
|
class GlobalAPIEtcTest < MiniTest::Test
|
196
|
+
def test_after
|
197
|
+
buffer = []
|
198
|
+
f = after(0.001) { buffer << 2 }
|
199
|
+
snooze
|
200
|
+
assert_equal [], buffer
|
201
|
+
sleep 0.001
|
202
|
+
assert_equal [2], buffer
|
203
|
+
end
|
204
|
+
|
198
205
|
def test_every
|
199
206
|
buffer = []
|
200
207
|
f = spin do
|
data/test/test_kernel.rb
CHANGED
@@ -21,6 +21,29 @@ class KernelTest < MiniTest::Test
|
|
21
21
|
timer&.stop
|
22
22
|
end
|
23
23
|
|
24
|
+
def patch_open3
|
25
|
+
class << Open3
|
26
|
+
alias_method :orig_popen2, :popen2
|
27
|
+
def popen2(*args)
|
28
|
+
raise SystemCallError, 'foo'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def unpatch_open3
|
34
|
+
class << Open3
|
35
|
+
alias_method :popen2, :orig_popen2
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_system_method_with_system_call_error
|
40
|
+
patch_open3
|
41
|
+
result = system('foo')
|
42
|
+
assert_nil result
|
43
|
+
ensure
|
44
|
+
unpatch_open3
|
45
|
+
end
|
46
|
+
|
24
47
|
def test_backtick_method
|
25
48
|
counter = 0
|
26
49
|
timer = spin { throttled_loop(200) { counter += 1 } }
|
data/test/test_signal.rb
CHANGED
data/test/test_thread.rb
CHANGED
@@ -50,7 +50,6 @@ class ThreadTest < MiniTest::Test
|
|
50
50
|
buffer = []
|
51
51
|
spin { (1..3).each { |i| snooze; buffer << i } }
|
52
52
|
t = Thread.new { sleep 0.01; buffer << 4; :foo }
|
53
|
-
|
54
53
|
r = t.await
|
55
54
|
|
56
55
|
assert_equal [1, 2, 3, 4], buffer
|
@@ -92,16 +91,18 @@ class ThreadTest < MiniTest::Test
|
|
92
91
|
lineno = __LINE__ + 1
|
93
92
|
t = Thread.new { sleep 1 }
|
94
93
|
str = format(
|
95
|
-
"#<Thread:%d %s:%d
|
94
|
+
"#<Thread:%d %s:%d",
|
96
95
|
t.object_id,
|
97
96
|
__FILE__,
|
98
97
|
lineno,
|
99
98
|
)
|
100
|
-
|
99
|
+
assert t.inspect =~ /#{str}/
|
101
100
|
rescue => e
|
102
101
|
p e
|
102
|
+
puts e.backtrace.join("\n")
|
103
103
|
ensure
|
104
104
|
t.kill
|
105
|
+
sleep 0.005
|
105
106
|
t.join
|
106
107
|
end
|
107
108
|
|
data/test/test_thread_pool.rb
CHANGED
@@ -65,10 +65,10 @@ class ThreadPoolTest < MiniTest::Test
|
|
65
65
|
end
|
66
66
|
elapsed = Time.now - t0
|
67
67
|
|
68
|
-
assert elapsed < 0.
|
68
|
+
assert elapsed < 0.007
|
69
69
|
assert buffer.size < 2
|
70
70
|
|
71
|
-
sleep 0.
|
71
|
+
sleep 0.08 # allow time for threads to spawn
|
72
72
|
assert_equal @pool.size, threads.uniq.size
|
73
73
|
assert_equal (0..9).to_a, buffer.sort
|
74
74
|
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.
|
4
|
+
version: '0.33'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: modulation
|
@@ -243,6 +243,7 @@ extra_rdoc_files:
|
|
243
243
|
- README.md
|
244
244
|
files:
|
245
245
|
- ".gitbook.yaml"
|
246
|
+
- ".github/workflows/test.yml"
|
246
247
|
- ".gitignore"
|
247
248
|
- ".rubocop.yml"
|
248
249
|
- ".vscode/launch.json"
|
@@ -402,6 +403,7 @@ files:
|
|
402
403
|
- test/eg.rb
|
403
404
|
- test/helper.rb
|
404
405
|
- test/run.rb
|
406
|
+
- test/stress.rb
|
405
407
|
- test/test_async.rb
|
406
408
|
- test/test_ext.rb
|
407
409
|
- test/test_fiber.rb
|
@@ -415,7 +417,7 @@ files:
|
|
415
417
|
- test/test_throttler.rb
|
416
418
|
- test/test_timer.rb
|
417
419
|
- test/test_trace.rb
|
418
|
-
homepage: https://
|
420
|
+
homepage: https://digital-fabric.github.io/polyphony
|
419
421
|
licenses:
|
420
422
|
- MIT
|
421
423
|
metadata:
|
@@ -445,5 +447,5 @@ requirements: []
|
|
445
447
|
rubygems_version: 3.0.6
|
446
448
|
signing_key:
|
447
449
|
specification_version: 4
|
448
|
-
summary:
|
450
|
+
summary: Fine grained concurrency for Ruby
|
449
451
|
test_files: []
|