polyphony 0.45.1 → 0.46.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/.github/workflows/test.yml +2 -0
- data/.gitmodules +0 -0
- data/CHANGELOG.md +35 -0
- data/Gemfile.lock +3 -3
- data/README.md +3 -3
- data/Rakefile +1 -1
- data/TODO.md +20 -14
- data/bin/test +4 -0
- data/examples/io/raw.rb +14 -0
- data/examples/io/reline.rb +18 -0
- data/examples/performance/fiber_transfer.rb +13 -4
- data/examples/performance/multi_snooze.rb +0 -1
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +8 -20
- data/ext/liburing/liburing.h +585 -0
- data/ext/liburing/liburing/README.md +4 -0
- data/ext/liburing/liburing/barrier.h +73 -0
- data/ext/liburing/liburing/compat.h +15 -0
- data/ext/liburing/liburing/io_uring.h +343 -0
- data/ext/liburing/queue.c +333 -0
- data/ext/liburing/register.c +187 -0
- data/ext/liburing/setup.c +210 -0
- data/ext/liburing/syscall.c +54 -0
- data/ext/liburing/syscall.h +18 -0
- data/ext/polyphony/backend.h +1 -15
- data/ext/polyphony/backend_common.h +120 -0
- data/ext/polyphony/backend_io_uring.c +919 -0
- data/ext/polyphony/backend_io_uring_context.c +73 -0
- data/ext/polyphony/backend_io_uring_context.h +52 -0
- data/ext/polyphony/{libev_backend.c → backend_libev.c} +241 -297
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/extconf.rb +31 -13
- data/ext/polyphony/fiber.c +107 -28
- data/ext/polyphony/libev.c +4 -0
- data/ext/polyphony/libev.h +8 -2
- data/ext/polyphony/liburing.c +8 -0
- data/ext/polyphony/playground.c +51 -0
- data/ext/polyphony/polyphony.c +6 -6
- data/ext/polyphony/polyphony.h +34 -14
- data/ext/polyphony/polyphony_ext.c +12 -4
- data/ext/polyphony/queue.c +1 -1
- data/ext/polyphony/runqueue.c +102 -0
- data/ext/polyphony/runqueue_ring_buffer.c +85 -0
- data/ext/polyphony/runqueue_ring_buffer.h +31 -0
- data/ext/polyphony/thread.c +42 -90
- data/lib/polyphony.rb +2 -2
- data/lib/polyphony/adapters/process.rb +0 -3
- data/lib/polyphony/adapters/trace.rb +2 -2
- data/lib/polyphony/core/exceptions.rb +0 -4
- data/lib/polyphony/core/global_api.rb +13 -11
- data/lib/polyphony/core/sync.rb +7 -5
- data/lib/polyphony/extensions/core.rb +14 -33
- data/lib/polyphony/extensions/debug.rb +13 -0
- data/lib/polyphony/extensions/fiber.rb +21 -44
- data/lib/polyphony/extensions/io.rb +15 -4
- data/lib/polyphony/extensions/openssl.rb +6 -0
- data/lib/polyphony/extensions/socket.rb +63 -10
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +36 -4
- data/test/io_uring_test.rb +55 -0
- data/test/stress.rb +4 -1
- data/test/test_backend.rb +15 -6
- data/test/test_ext.rb +1 -2
- data/test/test_fiber.rb +31 -24
- data/test/test_global_api.rb +71 -31
- data/test/test_io.rb +42 -0
- data/test/test_queue.rb +1 -1
- data/test/test_signal.rb +11 -8
- data/test/test_socket.rb +2 -2
- data/test/test_sync.rb +21 -0
- data/test/test_throttler.rb +3 -7
- data/test/test_trace.rb +7 -5
- metadata +31 -6
data/lib/polyphony/version.rb
CHANGED
data/polyphony.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
s.required_ruby_version = '>= 2.6'
|
23
23
|
|
24
|
-
s.add_development_dependency 'rake-compiler', '1.
|
24
|
+
s.add_development_dependency 'rake-compiler', '1.1.1'
|
25
25
|
s.add_development_dependency 'minitest', '5.13.0'
|
26
26
|
s.add_development_dependency 'minitest-reporters', '1.4.2'
|
27
27
|
s.add_development_dependency 'simplecov', '0.17.1'
|
data/test/helper.rb
CHANGED
@@ -22,29 +22,52 @@ class ::Fiber
|
|
22
22
|
attr_writer :auto_watcher
|
23
23
|
end
|
24
24
|
|
25
|
+
module ::Kernel
|
26
|
+
def trace(*args)
|
27
|
+
STDOUT.orig_write(format_trace(args))
|
28
|
+
end
|
29
|
+
|
30
|
+
def format_trace(args)
|
31
|
+
if args.first.is_a?(String)
|
32
|
+
if args.size > 1
|
33
|
+
format("%s: %p\n", args.shift, args)
|
34
|
+
else
|
35
|
+
format("%s\n", args.first)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
25
43
|
class MiniTest::Test
|
26
44
|
def setup
|
27
|
-
#
|
45
|
+
# trace "* setup #{self.name}"
|
28
46
|
if Fiber.current.children.size > 0
|
29
47
|
puts "Children left: #{Fiber.current.children.inspect}"
|
30
48
|
exit!
|
31
49
|
end
|
32
50
|
Fiber.current.setup_main_fiber
|
33
51
|
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
52
|
+
Thread.current.backend.finalize
|
34
53
|
Thread.current.backend = Polyphony::Backend.new
|
35
|
-
sleep 0
|
54
|
+
sleep 0
|
36
55
|
end
|
37
56
|
|
38
57
|
def teardown
|
39
|
-
#
|
58
|
+
# trace "* teardown #{self.name}"
|
40
59
|
Fiber.current.terminate_all_children
|
41
60
|
Fiber.current.await_all_children
|
42
|
-
Fiber.current.auto_watcher
|
61
|
+
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
43
62
|
rescue => e
|
44
63
|
puts e
|
45
64
|
puts e.backtrace.join("\n")
|
46
65
|
exit!
|
47
66
|
end
|
67
|
+
|
68
|
+
def fiber_tree(fiber)
|
69
|
+
{ fiber: fiber, children: fiber.children.map { |f| fiber_tree(f) } }
|
70
|
+
end
|
48
71
|
end
|
49
72
|
|
50
73
|
module Kernel
|
@@ -54,3 +77,12 @@ module Kernel
|
|
54
77
|
e
|
55
78
|
end
|
56
79
|
end
|
80
|
+
|
81
|
+
module Minitest::Assertions
|
82
|
+
def assert_in_range exp_range, act
|
83
|
+
msg = message(msg) { "Expected #{mu_pp(act)} to be in range #{mu_pp(exp_range)}" }
|
84
|
+
assert exp_range.include?(act), msg
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
puts "Polyphony backend: #{Thread.current.backend.kind}"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
::Exception.__disable_sanitized_backtrace__ = true
|
6
|
+
|
7
|
+
module ::Kernel
|
8
|
+
def trace(*args)
|
9
|
+
STDOUT.orig_write(format_trace(args))
|
10
|
+
end
|
11
|
+
|
12
|
+
def format_trace(args)
|
13
|
+
if args.first.is_a?(String)
|
14
|
+
if args.size > 1
|
15
|
+
format("%s: %p\n", args.shift, args)
|
16
|
+
else
|
17
|
+
format("%s\n", args.first)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
format("%p\n", args.size == 1 ? args.first : args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
i, o = IO.pipe
|
26
|
+
|
27
|
+
buf = []
|
28
|
+
f = spin do
|
29
|
+
buf << :ready
|
30
|
+
# loop do
|
31
|
+
# s = Thread.current.backend.read(i, +'', 6, false)
|
32
|
+
# trace read_result: s
|
33
|
+
# break if s.nil?
|
34
|
+
# buf << s
|
35
|
+
# rescue Exception => e
|
36
|
+
# trace exception: e
|
37
|
+
# raise e
|
38
|
+
# end
|
39
|
+
Thread.current.backend.read_loop(i) { |d| buf << d }
|
40
|
+
buf << :done
|
41
|
+
end
|
42
|
+
|
43
|
+
# writing always causes snoozing
|
44
|
+
o << 'foo'
|
45
|
+
o << 'bar'
|
46
|
+
trace '...closing'
|
47
|
+
o.close
|
48
|
+
trace '...closed'
|
49
|
+
|
50
|
+
f.await
|
51
|
+
|
52
|
+
raise "Bad result: #{buf.inspect}" unless buf == [:ready, 'foo', 'bar', :done]
|
53
|
+
|
54
|
+
puts '-' * 80
|
55
|
+
p buf
|
data/test/stress.rb
CHANGED
@@ -6,6 +6,7 @@ TEST_CMD = 'ruby test/run.rb'
|
|
6
6
|
|
7
7
|
def run_test(count)
|
8
8
|
puts "#{count}: running tests..."
|
9
|
+
# sleep 1
|
9
10
|
system(TEST_CMD)
|
10
11
|
return if $?.exitstatus == 0
|
11
12
|
|
@@ -15,7 +16,9 @@ end
|
|
15
16
|
|
16
17
|
trap('INT') { exit! }
|
17
18
|
t0 = Time.now
|
18
|
-
count.times
|
19
|
+
count.times do |i|
|
20
|
+
run_test(i + 1)
|
21
|
+
end
|
19
22
|
elapsed = Time.now - t0
|
20
23
|
puts format(
|
21
24
|
"Successfully ran %d tests in %f seconds (%f per test)",
|
data/test/test_backend.rb
CHANGED
@@ -85,7 +85,7 @@ class BackendTest < MiniTest::Test
|
|
85
85
|
i, o = IO.pipe
|
86
86
|
|
87
87
|
buf = []
|
88
|
-
spin do
|
88
|
+
f = spin do
|
89
89
|
buf << :ready
|
90
90
|
@backend.read_loop(i) { |d| buf << d }
|
91
91
|
buf << :done
|
@@ -96,9 +96,7 @@ class BackendTest < MiniTest::Test
|
|
96
96
|
o << 'bar'
|
97
97
|
o.close
|
98
98
|
|
99
|
-
|
100
|
-
6.times { snooze }
|
101
|
-
|
99
|
+
f.await
|
102
100
|
assert_equal [:ready, 'foo', 'bar', :done], buf
|
103
101
|
end
|
104
102
|
|
@@ -111,12 +109,12 @@ class BackendTest < MiniTest::Test
|
|
111
109
|
end
|
112
110
|
|
113
111
|
c1 = TCPSocket.new('127.0.0.1', 1234)
|
114
|
-
|
112
|
+
sleep 0.01
|
115
113
|
|
116
114
|
assert_equal 1, clients.size
|
117
115
|
|
118
116
|
c2 = TCPSocket.new('127.0.0.1', 1234)
|
119
|
-
|
117
|
+
sleep 0.01
|
120
118
|
|
121
119
|
assert_equal 2, clients.size
|
122
120
|
|
@@ -127,4 +125,15 @@ class BackendTest < MiniTest::Test
|
|
127
125
|
snooze
|
128
126
|
server&.close
|
129
127
|
end
|
128
|
+
|
129
|
+
def test_timer_loop
|
130
|
+
i = 0
|
131
|
+
f = spin do
|
132
|
+
@backend.timer_loop(0.01) { i += 1 }
|
133
|
+
end
|
134
|
+
@backend.sleep(0.05)
|
135
|
+
f.stop
|
136
|
+
f.await # TODO: check why this test sometimes segfaults if we don't a<wait fiber
|
137
|
+
assert_in_range 4..6, i
|
138
|
+
end
|
130
139
|
end
|
data/test/test_ext.rb
CHANGED
@@ -183,8 +183,7 @@ class TimeoutTest < MiniTest::Test
|
|
183
183
|
end
|
184
184
|
|
185
185
|
def test_that_timeout_method_accepts_custom_error_class_and_message
|
186
|
-
|
187
|
-
spin { 3.times { |i| buffer << i; snooze } }
|
186
|
+
e = nil
|
188
187
|
begin
|
189
188
|
Timeout.timeout(0.05, MyTimeout, 'foo') { sleep 1 }
|
190
189
|
rescue Exception => e
|
data/test/test_fiber.rb
CHANGED
@@ -62,7 +62,7 @@ class FiberTest < MiniTest::Test
|
|
62
62
|
assert_equal 0, Fiber.current.children.size
|
63
63
|
end
|
64
64
|
|
65
|
-
def test_await_from_multiple_fibers_with_interruption
|
65
|
+
def test_await_from_multiple_fibers_with_interruption=
|
66
66
|
buffer = []
|
67
67
|
f1 = spin {
|
68
68
|
sleep 0.02
|
@@ -128,15 +128,16 @@ class FiberTest < MiniTest::Test
|
|
128
128
|
worker&.join
|
129
129
|
end
|
130
130
|
|
131
|
-
def
|
132
|
-
|
131
|
+
def test_backend_wakeup_mechanism
|
132
|
+
event = Polyphony::Event.new
|
133
|
+
|
133
134
|
t = Thread.new do
|
134
135
|
f = spin_loop { snooze }
|
135
136
|
sleep 0.001
|
136
|
-
|
137
|
+
event.signal(:foo)
|
137
138
|
end
|
138
139
|
|
139
|
-
result = move_on_after(1) {
|
140
|
+
result = move_on_after(1) { event.await }
|
140
141
|
|
141
142
|
assert_equal :foo, result
|
142
143
|
ensure
|
@@ -469,12 +470,14 @@ class FiberTest < MiniTest::Test
|
|
469
470
|
end
|
470
471
|
snooze # allow nested fiber to run before finishing
|
471
472
|
end
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
473
|
+
begin
|
474
|
+
suspend
|
475
|
+
rescue Exception => e
|
476
|
+
raised_error = e
|
477
|
+
ensure
|
478
|
+
assert raised_error
|
479
|
+
assert_equal 'foo', raised_error.message
|
480
|
+
end
|
478
481
|
end
|
479
482
|
|
480
483
|
def test_await_multiple_fibers
|
@@ -631,11 +634,12 @@ class FiberTest < MiniTest::Test
|
|
631
634
|
def test_signal_handling_int
|
632
635
|
i, o = IO.pipe
|
633
636
|
pid = Polyphony.fork do
|
634
|
-
f = spin { sleep
|
637
|
+
f = spin { sleep 3 }
|
635
638
|
begin
|
636
639
|
i.close
|
637
640
|
f.await
|
638
641
|
rescue Exception => e
|
642
|
+
trace e
|
639
643
|
o << e.class.name
|
640
644
|
o.close
|
641
645
|
end
|
@@ -653,7 +657,7 @@ class FiberTest < MiniTest::Test
|
|
653
657
|
def test_signal_handling_term
|
654
658
|
i, o = IO.pipe
|
655
659
|
pid = Polyphony.fork do
|
656
|
-
f = spin { sleep
|
660
|
+
f = spin { sleep 3 }
|
657
661
|
begin
|
658
662
|
i.close
|
659
663
|
f.await
|
@@ -662,7 +666,7 @@ class FiberTest < MiniTest::Test
|
|
662
666
|
o.close
|
663
667
|
end
|
664
668
|
end
|
665
|
-
sleep 0.
|
669
|
+
sleep 0.1
|
666
670
|
f = spin { Thread.current.backend.waitpid(pid) }
|
667
671
|
o.close
|
668
672
|
Process.kill('TERM', pid)
|
@@ -677,7 +681,7 @@ class FiberTest < MiniTest::Test
|
|
677
681
|
pid = Polyphony.fork do
|
678
682
|
i.close
|
679
683
|
spin do
|
680
|
-
sleep
|
684
|
+
sleep 3
|
681
685
|
rescue Exception => e
|
682
686
|
o << e.class.to_s
|
683
687
|
o.close
|
@@ -687,7 +691,7 @@ class FiberTest < MiniTest::Test
|
|
687
691
|
end
|
688
692
|
o.close
|
689
693
|
spin do
|
690
|
-
sleep 0.
|
694
|
+
sleep 0.1
|
691
695
|
Process.kill('TERM', pid)
|
692
696
|
end
|
693
697
|
Thread.current.backend.waitpid(pid)
|
@@ -700,16 +704,19 @@ class FiberTest < MiniTest::Test
|
|
700
704
|
buffer = []
|
701
705
|
f = Fiber.new { buffer << receive }
|
702
706
|
|
703
|
-
|
707
|
+
assert_nil f.thread
|
704
708
|
snooze
|
705
709
|
f.setup_raw
|
710
|
+
|
706
711
|
assert_equal Thread.current, f.thread
|
707
712
|
assert_nil f.parent
|
708
713
|
|
709
714
|
f.schedule
|
715
|
+
snooze
|
710
716
|
f << 'bar'
|
711
|
-
|
717
|
+
snooze
|
712
718
|
assert_equal ['bar'], buffer
|
719
|
+
snooze
|
713
720
|
end
|
714
721
|
end
|
715
722
|
|
@@ -811,20 +818,20 @@ class MailboxTest < MiniTest::Test
|
|
811
818
|
assert_equal ['foo'] * 100, messages
|
812
819
|
end
|
813
820
|
|
814
|
-
def
|
815
|
-
assert_equal [],
|
821
|
+
def test_receive_all_pending
|
822
|
+
assert_equal [], receive_all_pending
|
816
823
|
|
817
824
|
(1..5).each { |i| Fiber.current << i }
|
818
|
-
assert_equal (1..5).to_a,
|
819
|
-
assert_equal [],
|
825
|
+
assert_equal (1..5).to_a, receive_all_pending
|
826
|
+
assert_equal [], receive_all_pending
|
820
827
|
end
|
821
828
|
|
822
|
-
def
|
829
|
+
def test_receive_all_pending_on_termination
|
823
830
|
buffer = []
|
824
831
|
worker = spin do
|
825
832
|
loop { buffer << receive }
|
826
833
|
rescue Polyphony::Terminate
|
827
|
-
|
834
|
+
receive_all_pending.each { |r| buffer << r }
|
828
835
|
end
|
829
836
|
|
830
837
|
worker << 1
|
data/test/test_global_api.rb
CHANGED
@@ -72,28 +72,32 @@ class ExceptionTest < MiniTest::Test
|
|
72
72
|
rescue Exception => e
|
73
73
|
frames << 3
|
74
74
|
raise e
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
end
|
76
|
+
begin
|
77
|
+
5.times { snooze }
|
78
|
+
rescue Exception => e
|
79
|
+
error = e
|
80
|
+
ensure
|
81
|
+
assert_kind_of RuntimeError, error
|
82
|
+
assert_equal [2, 3], frames
|
83
|
+
end
|
82
84
|
end
|
83
85
|
|
84
86
|
def test_cross_fiber_backtrace_with_dead_calling_fiber
|
85
87
|
error = nil
|
86
|
-
|
88
|
+
begin
|
87
89
|
spin do
|
88
90
|
spin do
|
89
|
-
|
91
|
+
spin do
|
92
|
+
raise 'foo'
|
93
|
+
end.await
|
90
94
|
end.await
|
91
95
|
end.await
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
96
|
+
rescue Exception => e
|
97
|
+
error = e
|
98
|
+
ensure
|
99
|
+
assert_kind_of RuntimeError, error
|
100
|
+
end
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
@@ -122,6 +126,20 @@ class MoveOnAfterTest < MiniTest::Test
|
|
122
126
|
assert_equal :bar, v
|
123
127
|
end
|
124
128
|
|
129
|
+
def test_move_on_after_with_reset
|
130
|
+
t0 = Time.now
|
131
|
+
v = move_on_after(0.01, with_value: :moved_on) do |timeout|
|
132
|
+
sleep 0.007
|
133
|
+
timeout.reset
|
134
|
+
sleep 0.007
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
t1 = Time.now
|
138
|
+
|
139
|
+
assert_nil v
|
140
|
+
assert_in_range 0.014..0.02, t1 - t0
|
141
|
+
end
|
142
|
+
|
125
143
|
def test_move_on_after_without_block
|
126
144
|
t0 = Time.now
|
127
145
|
f = move_on_after(0.01, with_value: 'foo')
|
@@ -160,6 +178,19 @@ class CancelAfterTest < MiniTest::Test
|
|
160
178
|
assert t1 - t0 < 0.1
|
161
179
|
end
|
162
180
|
|
181
|
+
def test_cancel_after_with_reset
|
182
|
+
t0 = Time.now
|
183
|
+
cancel_after(0.01) do |f|
|
184
|
+
assert_kind_of Fiber, f
|
185
|
+
assert_equal Fiber.current, f.parent
|
186
|
+
sleep 0.007
|
187
|
+
f.reset
|
188
|
+
sleep 0.007
|
189
|
+
end
|
190
|
+
t1 = Time.now
|
191
|
+
assert_in_range 0.014..0.02, t1 - t0
|
192
|
+
end
|
193
|
+
|
163
194
|
class CustomException < Exception
|
164
195
|
end
|
165
196
|
|
@@ -171,6 +202,19 @@ class CancelAfterTest < MiniTest::Test
|
|
171
202
|
end
|
172
203
|
end
|
173
204
|
|
205
|
+
begin
|
206
|
+
err = nil
|
207
|
+
cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
|
208
|
+
sleep 1
|
209
|
+
:foo
|
210
|
+
end
|
211
|
+
rescue Exception => err
|
212
|
+
ensure
|
213
|
+
assert_kind_of CustomException, err
|
214
|
+
assert_equal 'custom message', err.message
|
215
|
+
end
|
216
|
+
|
217
|
+
|
174
218
|
begin
|
175
219
|
e = nil
|
176
220
|
cancel_after(0.01, with_exception: 'foo') do
|
@@ -226,12 +270,10 @@ class SpinLoopTest < MiniTest::Test
|
|
226
270
|
buffer = []
|
227
271
|
counter = 0
|
228
272
|
t0 = Time.now
|
229
|
-
f = spin_loop(rate:
|
230
|
-
sleep 0.
|
273
|
+
f = spin_loop(rate: 100) { buffer << (counter += 1) }
|
274
|
+
sleep 0.02
|
231
275
|
f.stop
|
232
|
-
|
233
|
-
expected = (elapsed * 10).to_i
|
234
|
-
assert counter >= expected - 1 && counter <= expected + 1
|
276
|
+
assert_in_range 1..3, counter
|
235
277
|
end
|
236
278
|
end
|
237
279
|
|
@@ -241,22 +283,22 @@ class ThrottledLoopTest < MiniTest::Test
|
|
241
283
|
counter = 0
|
242
284
|
t0 = Time.now
|
243
285
|
f = spin do
|
244
|
-
throttled_loop(
|
286
|
+
throttled_loop(100) { buffer << (counter += 1) }
|
245
287
|
end
|
246
|
-
sleep 0.
|
247
|
-
|
248
|
-
elapsed = Time.now - t0
|
249
|
-
expected = (elapsed * 10).to_i
|
250
|
-
assert counter >= expected - 1 && counter <= expected + 1
|
288
|
+
sleep 0.03
|
289
|
+
assert_in_range 2..4, counter
|
251
290
|
end
|
252
291
|
|
253
292
|
def test_throttled_loop_with_count
|
254
293
|
buffer = []
|
255
294
|
counter = 0
|
295
|
+
t0 = Time.now
|
256
296
|
f = spin do
|
257
297
|
throttled_loop(50, count: 5) { buffer << (counter += 1) }
|
258
298
|
end
|
259
299
|
f.await
|
300
|
+
t1 = Time.now
|
301
|
+
assert_in_range 0.075..0.15, t1 - t0
|
260
302
|
assert_equal [1, 2, 3, 4, 5], buffer
|
261
303
|
end
|
262
304
|
end
|
@@ -275,13 +317,11 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
275
317
|
buffer = []
|
276
318
|
t0 = Time.now
|
277
319
|
f = spin do
|
278
|
-
every(0.
|
320
|
+
every(0.01) { buffer << 1 }
|
279
321
|
end
|
280
|
-
sleep 0.
|
322
|
+
sleep 0.05
|
281
323
|
f.stop
|
282
|
-
|
283
|
-
expected = (elapsed / 0.1).to_i
|
284
|
-
assert buffer.size >= expected - 2 && buffer.size <= expected + 2
|
324
|
+
assert_in_range 4..6, buffer.size
|
285
325
|
end
|
286
326
|
|
287
327
|
def test_sleep
|
@@ -349,4 +389,4 @@ class GlobalAPIEtcTest < MiniTest::Test
|
|
349
389
|
|
350
390
|
assert_equal [0, 1, 2], values
|
351
391
|
end
|
352
|
-
end
|
392
|
+
end
|