polyphony 0.40 → 0.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +11 -2
- data/.gitignore +2 -2
- data/.rubocop.yml +30 -0
- data/CHANGELOG.md +6 -2
- data/Gemfile.lock +9 -6
- data/Rakefile +2 -2
- data/TODO.md +18 -97
- data/docs/_includes/head.html +40 -0
- data/docs/_includes/nav.html +5 -5
- data/docs/api-reference/fiber.md +2 -2
- data/docs/main-concepts/design-principles.md +67 -9
- data/docs/main-concepts/extending.md +1 -1
- data/examples/core/xx-agent.rb +102 -0
- data/examples/core/xx-sleeping.rb +14 -6
- data/examples/io/xx-irb.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +7 -6
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +14 -25
- data/ext/{gyro → polyphony}/extconf.rb +2 -2
- data/ext/{gyro → polyphony}/fiber.c +15 -19
- data/ext/{gyro → polyphony}/libev.c +0 -0
- data/ext/{gyro → polyphony}/libev.h +0 -0
- data/ext/polyphony/libev_agent.c +503 -0
- data/ext/polyphony/libev_queue.c +214 -0
- data/ext/{gyro/gyro.c → polyphony/polyphony.c} +16 -25
- data/ext/polyphony/polyphony.h +90 -0
- data/ext/polyphony/polyphony_ext.c +23 -0
- data/ext/{gyro → polyphony}/socket.c +14 -14
- data/ext/{gyro → polyphony}/thread.c +32 -115
- data/ext/{gyro → polyphony}/tracing.c +1 -1
- data/lib/polyphony.rb +16 -12
- data/lib/polyphony/adapters/irb.rb +1 -1
- data/lib/polyphony/adapters/postgres.rb +6 -5
- data/lib/polyphony/adapters/process.rb +5 -5
- data/lib/polyphony/adapters/trace.rb +28 -28
- data/lib/polyphony/core/channel.rb +3 -3
- data/lib/polyphony/core/exceptions.rb +1 -1
- data/lib/polyphony/core/global_api.rb +11 -9
- data/lib/polyphony/core/resource_pool.rb +3 -3
- data/lib/polyphony/core/sync.rb +2 -2
- data/lib/polyphony/core/thread_pool.rb +6 -6
- data/lib/polyphony/core/throttler.rb +13 -6
- data/lib/polyphony/event.rb +27 -0
- data/lib/polyphony/extensions/core.rb +20 -11
- data/lib/polyphony/extensions/fiber.rb +4 -4
- data/lib/polyphony/extensions/io.rb +56 -26
- data/lib/polyphony/extensions/openssl.rb +4 -8
- data/lib/polyphony/extensions/socket.rb +27 -9
- data/lib/polyphony/extensions/thread.rb +16 -9
- data/lib/polyphony/net.rb +9 -9
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +2 -2
- data/test/helper.rb +12 -1
- data/test/test_agent.rb +77 -0
- data/test/{test_async.rb → test_event.rb} +13 -7
- data/test/test_ext.rb +25 -4
- data/test/test_fiber.rb +19 -10
- data/test/test_global_api.rb +4 -4
- data/test/test_io.rb +46 -24
- data/test/test_queue.rb +74 -0
- data/test/test_signal.rb +3 -40
- data/test/test_socket.rb +33 -0
- data/test/test_thread.rb +37 -16
- data/test/test_trace.rb +6 -5
- metadata +24 -24
- data/ext/gyro/async.c +0 -132
- data/ext/gyro/child.c +0 -108
- data/ext/gyro/gyro.h +0 -158
- data/ext/gyro/gyro_ext.c +0 -33
- data/ext/gyro/io.c +0 -457
- data/ext/gyro/queue.c +0 -146
- data/ext/gyro/selector.c +0 -205
- data/ext/gyro/signal.c +0 -99
- data/ext/gyro/timer.c +0 -115
- data/test/test_timer.rb +0 -56
data/test/test_fiber.rb
CHANGED
@@ -110,7 +110,7 @@ class FiberTest < MiniTest::Test
|
|
110
110
|
def test_cross_thread_schedule
|
111
111
|
buffer = []
|
112
112
|
worker_fiber = nil
|
113
|
-
async =
|
113
|
+
async = Polyphony::Event.new
|
114
114
|
worker = Thread.new do
|
115
115
|
worker_fiber = Fiber.current
|
116
116
|
async.signal
|
@@ -125,10 +125,11 @@ class FiberTest < MiniTest::Test
|
|
125
125
|
assert_equal [:foo], buffer
|
126
126
|
ensure
|
127
127
|
worker&.kill
|
128
|
+
worker&.join
|
128
129
|
end
|
129
130
|
|
130
131
|
def test_ev_loop_anti_starve_mechanism
|
131
|
-
async =
|
132
|
+
async = Polyphony::Event.new
|
132
133
|
t = Thread.new do
|
133
134
|
f = spin_loop { snooze }
|
134
135
|
sleep 0.001
|
@@ -139,7 +140,8 @@ class FiberTest < MiniTest::Test
|
|
139
140
|
|
140
141
|
assert_equal :foo, result
|
141
142
|
ensure
|
142
|
-
t
|
143
|
+
t&.kill
|
144
|
+
t&.join
|
143
145
|
end
|
144
146
|
|
145
147
|
def test_tag
|
@@ -350,8 +352,7 @@ class FiberTest < MiniTest::Test
|
|
350
352
|
result = []
|
351
353
|
f = Fiber.current.spin do
|
352
354
|
result << :start
|
353
|
-
|
354
|
-
result << t.await
|
355
|
+
result << Thread.current.agent.sleep(1)
|
355
356
|
end
|
356
357
|
snooze
|
357
358
|
f.interrupt
|
@@ -624,7 +625,7 @@ class FiberTest < MiniTest::Test
|
|
624
625
|
end
|
625
626
|
end
|
626
627
|
sleep 0.1
|
627
|
-
f = spin {
|
628
|
+
f = spin { Thread.current.agent.waitpid(pid) }
|
628
629
|
o.close
|
629
630
|
Process.kill('INT', pid)
|
630
631
|
f.await
|
@@ -646,7 +647,7 @@ class FiberTest < MiniTest::Test
|
|
646
647
|
end
|
647
648
|
end
|
648
649
|
sleep 0.2
|
649
|
-
f = spin {
|
650
|
+
f = spin { Thread.current.agent.waitpid(pid) }
|
650
651
|
o.close
|
651
652
|
Process.kill('TERM', pid)
|
652
653
|
f.await
|
@@ -673,7 +674,7 @@ class FiberTest < MiniTest::Test
|
|
673
674
|
sleep 0.2
|
674
675
|
Process.kill('TERM', pid)
|
675
676
|
end
|
676
|
-
|
677
|
+
Thread.current.agent.waitpid(pid)
|
677
678
|
klass = i.read
|
678
679
|
i.close
|
679
680
|
assert_equal 'Polyphony::Terminate', klass
|
@@ -707,6 +708,7 @@ class MailboxTest < MiniTest::Test
|
|
707
708
|
f << i
|
708
709
|
sleep 0
|
709
710
|
end
|
711
|
+
sleep 0
|
710
712
|
|
711
713
|
assert_equal [0, 1, 2], msgs
|
712
714
|
ensure
|
@@ -717,11 +719,11 @@ class MailboxTest < MiniTest::Test
|
|
717
719
|
msgs = []
|
718
720
|
f = spin { loop { msgs << receive } }
|
719
721
|
|
720
|
-
snooze # allow
|
722
|
+
snooze # allow f to start
|
721
723
|
|
722
724
|
3.times { |i| f << i }
|
723
725
|
|
724
|
-
sleep 0
|
726
|
+
sleep 0.01
|
725
727
|
|
726
728
|
assert_equal [0, 1, 2], msgs
|
727
729
|
ensure
|
@@ -743,6 +745,7 @@ class MailboxTest < MiniTest::Test
|
|
743
745
|
def test_cross_thread_send_receive
|
744
746
|
ping_receive_buffer = []
|
745
747
|
pong_receive_buffer = []
|
748
|
+
|
746
749
|
pong = Thread.new do
|
747
750
|
sleep 0.05
|
748
751
|
loop do
|
@@ -763,9 +766,15 @@ class MailboxTest < MiniTest::Test
|
|
763
766
|
|
764
767
|
ping.join
|
765
768
|
pong.kill
|
769
|
+
ping = pong = nil
|
766
770
|
|
767
771
|
assert_equal %w{pong pong pong}, ping_receive_buffer
|
768
772
|
assert_equal %w{ping ping ping}, pong_receive_buffer
|
773
|
+
ensure
|
774
|
+
pong&.kill
|
775
|
+
ping&.kill
|
776
|
+
pong&.join
|
777
|
+
ping&.join
|
769
778
|
end
|
770
779
|
|
771
780
|
def test_message_queueing
|
data/test/test_global_api.rb
CHANGED
@@ -202,9 +202,9 @@ class SpinLoopTest < MiniTest::Test
|
|
202
202
|
buffer = []
|
203
203
|
counter = 0
|
204
204
|
f = spin_loop(rate: 50) { buffer << (counter += 1) }
|
205
|
-
sleep 0.
|
205
|
+
sleep 0.2
|
206
206
|
f.stop
|
207
|
-
assert counter >=
|
207
|
+
assert counter >= 9 && counter <= 11
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
@@ -215,9 +215,9 @@ class ThrottledLoopTest < MiniTest::Test
|
|
215
215
|
f = spin do
|
216
216
|
throttled_loop(50) { buffer << (counter += 1) }
|
217
217
|
end
|
218
|
-
sleep 0.
|
218
|
+
sleep 0.2
|
219
219
|
f.stop
|
220
|
-
assert counter >=
|
220
|
+
assert counter >= 9 && counter <= 11
|
221
221
|
end
|
222
222
|
|
223
223
|
def test_throttled_loop_with_count
|
data/test/test_io.rb
CHANGED
@@ -2,30 +2,6 @@
|
|
2
2
|
|
3
3
|
require_relative 'helper'
|
4
4
|
|
5
|
-
class GyroIOTest < MiniTest::Test
|
6
|
-
def test_that_reading_works
|
7
|
-
i, o = IO.pipe
|
8
|
-
data = +''
|
9
|
-
sequence = []
|
10
|
-
watcher = Gyro::IO.new(i, :r)
|
11
|
-
spin {
|
12
|
-
sequence << 1
|
13
|
-
watcher.await
|
14
|
-
sequence << 2
|
15
|
-
i.read_nonblock(8192, data)
|
16
|
-
}
|
17
|
-
snooze
|
18
|
-
sequence << 3
|
19
|
-
spin do
|
20
|
-
o << 'hello'
|
21
|
-
sequence << 4
|
22
|
-
end
|
23
|
-
suspend
|
24
|
-
assert_equal 'hello', data
|
25
|
-
assert_equal [1, 3, 4, 2], sequence
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
5
|
class IOTest < MiniTest::Test
|
30
6
|
def setup
|
31
7
|
super
|
@@ -61,6 +37,52 @@ class IOTest < MiniTest::Test
|
|
61
37
|
@o.close
|
62
38
|
assert_equal 'foobarbaz', @i.read
|
63
39
|
end
|
40
|
+
|
41
|
+
def test_wait_io
|
42
|
+
results = []
|
43
|
+
i, o = IO.pipe
|
44
|
+
f = spin do
|
45
|
+
loop do
|
46
|
+
result = i.orig_read_nonblock(8192, exception: false)
|
47
|
+
results << result
|
48
|
+
case result
|
49
|
+
when :wait_readable
|
50
|
+
Thread.current.agent.wait_io(i, false)
|
51
|
+
else
|
52
|
+
break result
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
snooze
|
58
|
+
o.write('foo')
|
59
|
+
o.close
|
60
|
+
|
61
|
+
result = f.await
|
62
|
+
|
63
|
+
assert_equal 'foo', f.await
|
64
|
+
assert_equal [:wait_readable, 'foo'], results
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_readpartial
|
68
|
+
i, o = IO.pipe
|
69
|
+
|
70
|
+
o << 'hi'
|
71
|
+
assert_equal 'hi', i.readpartial(3)
|
72
|
+
|
73
|
+
o << 'hi'
|
74
|
+
assert_equal 'h', i.readpartial(1)
|
75
|
+
assert_equal 'i', i.readpartial(1)
|
76
|
+
|
77
|
+
spin {
|
78
|
+
sleep 0.01
|
79
|
+
o << 'hi'
|
80
|
+
}
|
81
|
+
assert_equal 'hi', i.readpartial(2)
|
82
|
+
o.close
|
83
|
+
|
84
|
+
assert_raises(EOFError) { i.readpartial(1) }
|
85
|
+
end
|
64
86
|
end
|
65
87
|
|
66
88
|
class IOClassMethodsTest < MiniTest::Test
|
data/test/test_queue.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
class QueueTest < MiniTest::Test
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
@queue = Polyphony::Queue.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_pop
|
12
|
+
spin {
|
13
|
+
@queue << 42
|
14
|
+
}
|
15
|
+
v = @queue.shift
|
16
|
+
assert_equal 42, v
|
17
|
+
|
18
|
+
(1..4).each { |i| @queue << i }
|
19
|
+
buf = []
|
20
|
+
4.times { buf << @queue.shift }
|
21
|
+
assert_equal [1, 2, 3, 4], buf
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_multiple_waiters
|
25
|
+
a = spin { @queue.shift }
|
26
|
+
b = spin { @queue.shift }
|
27
|
+
|
28
|
+
@queue << :foo
|
29
|
+
@queue << :bar
|
30
|
+
|
31
|
+
assert_equal [:foo, :bar], Fiber.await(a, b)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_multi_thread_usage
|
35
|
+
t = Thread.new { @queue.push :foo }
|
36
|
+
assert_equal :foo, @queue.shift
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_shift_each
|
40
|
+
(1..4).each { |i| @queue << i }
|
41
|
+
buf = []
|
42
|
+
@queue.shift_each { |i| buf << i }
|
43
|
+
assert_equal [1, 2, 3, 4], buf
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_empty?
|
47
|
+
assert @queue.empty?
|
48
|
+
|
49
|
+
@queue << :foo
|
50
|
+
assert !@queue.empty?
|
51
|
+
|
52
|
+
assert_equal :foo, @queue.shift
|
53
|
+
assert @queue.empty?
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_fiber_removal_from_queue
|
57
|
+
f1 = spin { @queue.shift }
|
58
|
+
f2 = spin { @queue.shift }
|
59
|
+
f3 = spin { @queue.shift }
|
60
|
+
|
61
|
+
# let fibers run
|
62
|
+
snooze
|
63
|
+
|
64
|
+
f2.stop
|
65
|
+
snooze
|
66
|
+
|
67
|
+
@queue << :foo
|
68
|
+
@queue << :bar
|
69
|
+
|
70
|
+
assert_equal :foo, f1.await
|
71
|
+
assert_nil f2.await
|
72
|
+
assert_equal :bar, f3.await
|
73
|
+
end
|
74
|
+
end
|
data/test/test_signal.rb
CHANGED
@@ -2,41 +2,6 @@
|
|
2
2
|
|
3
3
|
require_relative 'helper'
|
4
4
|
|
5
|
-
class SignalTest < MiniTest::Test
|
6
|
-
def test_Gyro_Signal_constructor
|
7
|
-
sig = Signal.list['USR1']
|
8
|
-
count = 0
|
9
|
-
w = Gyro::Signal.new(sig)
|
10
|
-
|
11
|
-
spin {
|
12
|
-
loop {
|
13
|
-
w.await
|
14
|
-
count += 1
|
15
|
-
break
|
16
|
-
}
|
17
|
-
}
|
18
|
-
Thread.new do
|
19
|
-
orig_sleep 0.001
|
20
|
-
Process.kill(:USR1, Process.pid)
|
21
|
-
end
|
22
|
-
suspend
|
23
|
-
assert_equal 1, count
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_wait_for_signal_api
|
27
|
-
count = 0
|
28
|
-
spin do
|
29
|
-
Polyphony.wait_for_signal 'SIGHUP'
|
30
|
-
count += 1
|
31
|
-
end
|
32
|
-
|
33
|
-
snooze
|
34
|
-
Process.kill(:HUP, Process.pid)
|
35
|
-
snooze
|
36
|
-
assert_equal 1, count
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
5
|
class SignalTrapTest < Minitest::Test
|
41
6
|
def test_signal_exception_handling
|
42
7
|
i, o = IO.pipe
|
@@ -57,9 +22,8 @@ class SignalTrapTest < Minitest::Test
|
|
57
22
|
end
|
58
23
|
sleep 0.01
|
59
24
|
o.close
|
60
|
-
watcher = Gyro::Child.new(pid)
|
61
25
|
Process.kill('INT', pid)
|
62
|
-
|
26
|
+
Thread.current.agent.waitpid(pid)
|
63
27
|
buffer = i.read
|
64
28
|
assert_equal "3-interrupt\n", buffer
|
65
29
|
end
|
@@ -86,9 +50,8 @@ class SignalTrapTest < Minitest::Test
|
|
86
50
|
end
|
87
51
|
sleep 0.02
|
88
52
|
o.close
|
89
|
-
watcher = Gyro::Child.new(pid)
|
90
53
|
Process.kill('INT', pid)
|
91
|
-
|
54
|
+
Thread.current.agent.waitpid(pid)
|
92
55
|
buffer = i.read
|
93
56
|
assert_equal "3 - interrupted\n2 - terminated\n1 - terminated\n", buffer
|
94
57
|
end
|
@@ -130,7 +93,7 @@ class SignalTrapTest < Minitest::Test
|
|
130
93
|
o.close
|
131
94
|
sleep 0.1
|
132
95
|
Process.kill('INT', pid)
|
133
|
-
|
96
|
+
Thread.current.agent.waitpid(pid)
|
134
97
|
buffer = i.read
|
135
98
|
assert_equal "3-interrupt\n", buffer
|
136
99
|
end
|
data/test/test_socket.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
class SocketTest < MiniTest::Test
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_tcp
|
11
|
+
server = TCPServer.new('127.0.0.1', 1234)
|
12
|
+
|
13
|
+
server_fiber = spin do
|
14
|
+
while (socket = server.accept)
|
15
|
+
spin do
|
16
|
+
while (data = socket.gets(8192))
|
17
|
+
socket << data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
snooze
|
24
|
+
client = TCPSocket.new('127.0.0.1', 1234)
|
25
|
+
client.write("1234\n")
|
26
|
+
assert_equal "1234\n", client.readpartial(8192)
|
27
|
+
client.close
|
28
|
+
ensure
|
29
|
+
server_fiber.stop
|
30
|
+
snooze
|
31
|
+
server&.close
|
32
|
+
end
|
33
|
+
end
|
data/test/test_thread.rb
CHANGED
@@ -8,14 +8,20 @@ class ThreadTest < MiniTest::Test
|
|
8
8
|
buffer = []
|
9
9
|
f = spin { (1..3).each { |i| snooze; buffer << i } }
|
10
10
|
t = Thread.new do
|
11
|
+
sleep 0.01
|
11
12
|
s1 = spin { (11..13).each { |i| snooze; buffer << i } }
|
12
13
|
s2 = spin { (21..23).each { |i| snooze; buffer << i } }
|
14
|
+
sleep 0.02
|
13
15
|
Fiber.current.await_all_children
|
14
16
|
end
|
15
17
|
f.join
|
16
18
|
t.join
|
19
|
+
t = nil
|
17
20
|
|
18
21
|
assert_equal [1, 2, 3, 11, 12, 13, 21, 22, 23], buffer.sort
|
22
|
+
ensure
|
23
|
+
t&.kill
|
24
|
+
t&.join
|
19
25
|
end
|
20
26
|
|
21
27
|
def test_thread_join
|
@@ -24,11 +30,13 @@ class ThreadTest < MiniTest::Test
|
|
24
30
|
t = Thread.new { sleep 0.01; buffer << 4; :foo }
|
25
31
|
|
26
32
|
r = t.join
|
33
|
+
t = nil
|
27
34
|
|
28
|
-
assert_equal [1, 2, 3, 4], buffer
|
29
35
|
assert_equal :foo, r
|
36
|
+
assert_equal [1, 2, 3, 4], buffer
|
30
37
|
ensure
|
31
|
-
t
|
38
|
+
t&.kill
|
39
|
+
t&.join
|
32
40
|
end
|
33
41
|
|
34
42
|
def test_thread_join_with_timeout
|
@@ -37,6 +45,7 @@ class ThreadTest < MiniTest::Test
|
|
37
45
|
t = Thread.new { sleep 1; buffer << 4 }
|
38
46
|
t0 = Time.now
|
39
47
|
r = t.join(0.01)
|
48
|
+
t = nil
|
40
49
|
|
41
50
|
assert Time.now - t0 < 0.2
|
42
51
|
assert_equal [1, 2, 3], buffer
|
@@ -44,7 +53,8 @@ class ThreadTest < MiniTest::Test
|
|
44
53
|
ensure
|
45
54
|
# killing the thread will prevent stopping the sleep timer, as well as the
|
46
55
|
# thread's event selector, leading to a memory leak.
|
47
|
-
t&.kill
|
56
|
+
t&.kill
|
57
|
+
t&.join
|
48
58
|
end
|
49
59
|
|
50
60
|
def test_thread_await_alias_method
|
@@ -52,11 +62,13 @@ class ThreadTest < MiniTest::Test
|
|
52
62
|
spin { (1..3).each { |i| snooze; buffer << i } }
|
53
63
|
t = Thread.new { sleep 0.01; buffer << 4; :foo }
|
54
64
|
r = t.await
|
65
|
+
t = nil
|
55
66
|
|
56
67
|
assert_equal [1, 2, 3, 4], buffer
|
57
68
|
assert_equal :foo, r
|
58
69
|
ensure
|
59
|
-
t
|
70
|
+
t&.kill
|
71
|
+
t&.join
|
60
72
|
end
|
61
73
|
|
62
74
|
def test_join_race_condition_on_thread_spawning
|
@@ -65,27 +77,33 @@ class ThreadTest < MiniTest::Test
|
|
65
77
|
:foo
|
66
78
|
end
|
67
79
|
r = t.join
|
80
|
+
t = nil
|
68
81
|
assert_equal :foo, r
|
82
|
+
ensure
|
83
|
+
t&.kill
|
84
|
+
t&.join
|
69
85
|
end
|
70
86
|
|
71
87
|
def test_thread_uncaught_exception_propagation
|
72
|
-
|
73
|
-
sleep 1
|
74
|
-
end
|
75
|
-
snooze
|
76
|
-
t.kill
|
77
|
-
t.await
|
88
|
+
ready = Polyphony::Event.new
|
78
89
|
|
79
90
|
t = Thread.new do
|
91
|
+
ready.signal
|
92
|
+
sleep 0.01
|
80
93
|
raise 'foo'
|
81
94
|
end
|
82
95
|
e = nil
|
83
96
|
begin
|
84
|
-
|
97
|
+
ready.await
|
98
|
+
r = t.await
|
85
99
|
rescue Exception => e
|
86
100
|
end
|
101
|
+
t = nil
|
87
102
|
assert_kind_of RuntimeError, e
|
88
103
|
assert_equal 'foo', e.message
|
104
|
+
ensure
|
105
|
+
t&.kill
|
106
|
+
t&.join
|
89
107
|
end
|
90
108
|
|
91
109
|
def test_thread_inspect
|
@@ -102,9 +120,8 @@ class ThreadTest < MiniTest::Test
|
|
102
120
|
p e
|
103
121
|
puts e.backtrace.join("\n")
|
104
122
|
ensure
|
105
|
-
t
|
106
|
-
|
107
|
-
t.join
|
123
|
+
t&.kill
|
124
|
+
t&.join
|
108
125
|
end
|
109
126
|
|
110
127
|
def test_that_suspend_returns_immediately_if_no_watchers
|
@@ -113,14 +130,14 @@ class ThreadTest < MiniTest::Test
|
|
113
130
|
records << r if r[:event] =~ /^fiber_/
|
114
131
|
end
|
115
132
|
t.enable
|
116
|
-
|
133
|
+
Polyphony.trace(true)
|
117
134
|
|
118
135
|
suspend
|
119
136
|
t.disable
|
120
137
|
assert_equal [:fiber_switchpoint], records.map { |r| r[:event] }
|
121
138
|
ensure
|
122
139
|
t&.disable
|
123
|
-
|
140
|
+
Polyphony.trace(false)
|
124
141
|
end
|
125
142
|
|
126
143
|
def test_thread_child_fiber_termination
|
@@ -143,7 +160,11 @@ class ThreadTest < MiniTest::Test
|
|
143
160
|
assert_equal 2, t.main_fiber.children.size
|
144
161
|
t.kill
|
145
162
|
t.join
|
163
|
+
t = nil
|
146
164
|
|
147
165
|
assert_equal [:foo, :bar], buffer
|
166
|
+
ensure
|
167
|
+
t&.kill
|
168
|
+
t&.join
|
148
169
|
end
|
149
170
|
end
|