polyphony 0.45.0 → 0.46.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -0
  3. data/.gitmodules +0 -0
  4. data/.rubocop.yml +1 -0
  5. data/CHANGELOG.md +38 -0
  6. data/Gemfile.lock +11 -3
  7. data/README.md +3 -3
  8. data/Rakefile +1 -1
  9. data/TODO.md +10 -18
  10. data/examples/adapters/redis_client.rb +3 -1
  11. data/examples/adapters/redis_pubsub_perf.rb +11 -8
  12. data/examples/adapters/sequel_mysql.rb +1 -1
  13. data/examples/adapters/sequel_pg.rb +24 -0
  14. data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
  15. data/examples/core/{xx-channels.rb → channels.rb} +0 -0
  16. data/examples/core/deferring-an-operation.rb +16 -0
  17. data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
  18. data/examples/core/{xx-forking.rb → forking.rb} +1 -1
  19. data/examples/core/handling-signals.rb +11 -0
  20. data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
  21. data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
  22. data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
  23. data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
  24. data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
  25. data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
  26. data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
  27. data/examples/core/supervisor.rb +20 -0
  28. data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
  29. data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
  30. data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
  31. data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
  32. data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
  33. data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
  34. data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
  35. data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
  36. data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
  37. data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
  38. data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
  39. data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
  40. data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
  41. data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
  42. data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
  43. data/examples/io/{xx-irb.rb → irb.rb} +0 -0
  44. data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
  45. data/examples/io/{xx-open.rb → open.rb} +0 -0
  46. data/examples/io/{xx-pry.rb → pry.rb} +0 -0
  47. data/examples/io/{xx-rack_server.rb → rack_server.rb} +0 -0
  48. data/examples/io/raw.rb +14 -0
  49. data/examples/io/reline.rb +18 -0
  50. data/examples/io/{xx-system.rb → system.rb} +1 -1
  51. data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
  52. data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
  53. data/examples/io/tunnel.rb +6 -1
  54. data/examples/io/{xx-zip.rb → zip.rb} +0 -0
  55. data/examples/performance/fiber_transfer.rb +2 -1
  56. data/examples/performance/fs_read.rb +5 -6
  57. data/examples/performance/multi_snooze.rb +0 -1
  58. data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
  59. data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
  60. data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
  61. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
  62. data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -2
  63. data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
  64. data/examples/performance/thread_pool_perf.rb +6 -7
  65. data/ext/liburing/liburing.h +585 -0
  66. data/ext/liburing/liburing/README.md +4 -0
  67. data/ext/liburing/liburing/barrier.h +73 -0
  68. data/ext/liburing/liburing/compat.h +15 -0
  69. data/ext/liburing/liburing/io_uring.h +343 -0
  70. data/ext/liburing/queue.c +333 -0
  71. data/ext/liburing/register.c +187 -0
  72. data/ext/liburing/setup.c +210 -0
  73. data/ext/liburing/syscall.c +54 -0
  74. data/ext/liburing/syscall.h +18 -0
  75. data/ext/polyphony/backend.h +1 -16
  76. data/ext/polyphony/backend_common.h +109 -0
  77. data/ext/polyphony/backend_io_uring.c +884 -0
  78. data/ext/polyphony/backend_io_uring_context.c +73 -0
  79. data/ext/polyphony/backend_io_uring_context.h +52 -0
  80. data/ext/polyphony/{libev_backend.c → backend_libev.c} +255 -345
  81. data/ext/polyphony/event.c +1 -1
  82. data/ext/polyphony/extconf.rb +31 -13
  83. data/ext/polyphony/fiber.c +111 -27
  84. data/ext/polyphony/libev.c +4 -0
  85. data/ext/polyphony/libev.h +8 -2
  86. data/ext/polyphony/liburing.c +8 -0
  87. data/ext/polyphony/playground.c +51 -0
  88. data/ext/polyphony/polyphony.c +6 -8
  89. data/ext/polyphony/polyphony.h +29 -25
  90. data/ext/polyphony/polyphony_ext.c +13 -6
  91. data/ext/polyphony/queue.c +3 -4
  92. data/ext/polyphony/ring_buffer.c +0 -1
  93. data/ext/polyphony/runqueue.c +102 -0
  94. data/ext/polyphony/runqueue_ring_buffer.c +85 -0
  95. data/ext/polyphony/runqueue_ring_buffer.h +31 -0
  96. data/ext/polyphony/thread.c +45 -92
  97. data/lib/polyphony.rb +2 -2
  98. data/lib/polyphony/adapters/fs.rb +1 -1
  99. data/lib/polyphony/adapters/process.rb +0 -3
  100. data/lib/polyphony/adapters/redis.rb +1 -1
  101. data/lib/polyphony/adapters/trace.rb +2 -2
  102. data/lib/polyphony/core/global_api.rb +9 -12
  103. data/lib/polyphony/core/sync.rb +6 -2
  104. data/lib/polyphony/extensions/core.rb +6 -24
  105. data/lib/polyphony/extensions/debug.rb +13 -0
  106. data/lib/polyphony/extensions/fiber.rb +21 -44
  107. data/lib/polyphony/extensions/io.rb +55 -10
  108. data/lib/polyphony/extensions/socket.rb +70 -12
  109. data/lib/polyphony/version.rb +1 -1
  110. data/polyphony.gemspec +3 -2
  111. data/test/helper.rb +36 -4
  112. data/test/io_uring_test.rb +55 -0
  113. data/test/stress.rb +5 -2
  114. data/test/test_backend.rb +4 -6
  115. data/test/test_ext.rb +1 -2
  116. data/test/test_fiber.rb +31 -24
  117. data/test/test_global_api.rb +58 -31
  118. data/test/test_io.rb +58 -0
  119. data/test/test_signal.rb +11 -8
  120. data/test/test_socket.rb +17 -0
  121. data/test/test_sync.rb +21 -0
  122. data/test/test_throttler.rb +3 -6
  123. data/test/test_trace.rb +7 -5
  124. metadata +86 -76
  125. data/examples/adapters/concurrent-ruby.rb +0 -9
  126. data/examples/core/04-handling-signals.rb +0 -19
  127. data/examples/core/xx-at_exit.rb +0 -29
  128. data/examples/core/xx-backend.rb +0 -102
  129. data/examples/core/xx-caller.rb +0 -12
  130. data/examples/core/xx-daemon.rb +0 -14
  131. data/examples/core/xx-deadlock.rb +0 -8
  132. data/examples/core/xx-deferring-an-operation.rb +0 -14
  133. data/examples/core/xx-exception-backtrace.rb +0 -40
  134. data/examples/core/xx-fork-cleanup.rb +0 -22
  135. data/examples/core/xx-fork-spin.rb +0 -42
  136. data/examples/core/xx-fork-terminate.rb +0 -27
  137. data/examples/core/xx-move_on.rb +0 -23
  138. data/examples/core/xx-queue-async.rb +0 -120
  139. data/examples/core/xx-readpartial.rb +0 -18
  140. data/examples/core/xx-signals.rb +0 -16
  141. data/examples/core/xx-sleep-forever.rb +0 -9
  142. data/examples/core/xx-sleeping.rb +0 -25
  143. data/examples/core/xx-snooze-starve.rb +0 -16
  144. data/examples/core/xx-spin-fork.rb +0 -49
  145. data/examples/core/xx-state-machine.rb +0 -51
  146. data/examples/core/xx-stop.rb +0 -20
  147. data/examples/core/xx-supervisors.rb +0 -21
  148. data/examples/core/xx-thread-selector-sleep.rb +0 -51
  149. data/examples/core/xx-thread-selector-snooze.rb +0 -46
  150. data/examples/core/xx-thread-snooze.rb +0 -34
  151. data/examples/core/xx-timer-gc.rb +0 -17
  152. data/examples/core/xx-trace.rb +0 -79
  153. data/examples/performance/xx-array.rb +0 -11
  154. data/examples/performance/xx-fiber-switch.rb +0 -9
  155. data/examples/performance/xx-snooze.rb +0 -15
  156. data/examples/xx-spin.rb +0 -32
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.45.0'
4
+ VERSION = '0.46.0'
5
5
  end
@@ -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.0.5'
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'
@@ -32,9 +32,10 @@ Gem::Specification.new do |s|
32
32
  s.add_development_dependency 'redis', '4.1.0'
33
33
  s.add_development_dependency 'hiredis', '0.6.3'
34
34
  s.add_development_dependency 'http_parser.rb', '~>0.6.0'
35
- s.add_development_dependency 'rack', '>=2.0.8', '<2.3.0'
35
+ s.add_development_dependency 'rack', '>=2.0.8', '<2.3.0'
36
36
  s.add_development_dependency 'mysql2', '0.5.3'
37
37
  s.add_development_dependency 'sequel', '5.34.0'
38
+ s.add_development_dependency 'httparty', '0.17.1'
38
39
 
39
40
  s.add_development_dependency 'jekyll', '~>3.8.6'
40
41
  s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'
@@ -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
- # puts "* setup #{self.name}"
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 # apparently this helps with timer accuracy
54
+ sleep 0
36
55
  end
37
56
 
38
57
  def teardown
39
- # puts "* teardown #{self.name.inspect} Fiber.current: #{Fiber.current.inspect}"
58
+ # trace "* teardown #{self.name}"
40
59
  Fiber.current.terminate_all_children
41
60
  Fiber.current.await_all_children
42
- Fiber.current.auto_watcher = nil
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
@@ -2,10 +2,11 @@
2
2
 
3
3
  count = ARGV[0] ? ARGV[0].to_i : 100
4
4
 
5
- TEST_CMD = 'ruby test/run.rb'
5
+ TEST_CMD = 'ruby test/test_backend.rb' #'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 { |i| run_test(i + 1) }
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)",
@@ -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
- # read_loop will snooze after every read
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
- 10.times { snooze }
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
- 10.times { snooze }
117
+ sleep 0.01
120
118
 
121
119
  assert_equal 2, clients.size
122
120
 
@@ -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
- buffer = []
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
@@ -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 test_ev_loop_anti_starve_mechanism
132
- async = Polyphony::Event.new
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
- async.signal(:foo)
137
+ event.signal(:foo)
137
138
  end
138
139
 
139
- result = move_on_after(1) { async.await }
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
- suspend
473
- rescue Exception => e
474
- raised_error = e
475
- ensure
476
- assert raised_error
477
- assert_equal 'foo', raised_error.message
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 100 }
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 100 }
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.2
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 100
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.2
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
- assert_raises(NoMethodError) { f << 'foo' }
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
- 2.times { snooze }
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 test_receive_pending
815
- assert_equal [], receive_pending
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, receive_pending
819
- assert_equal [], receive_pending
825
+ assert_equal (1..5).to_a, receive_all_pending
826
+ assert_equal [], receive_all_pending
820
827
  end
821
828
 
822
- def test_receive_pending_on_termination
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
- receive_pending.each { |r| buffer << r }
834
+ receive_all_pending.each { |r| buffer << r }
828
835
  end
829
836
 
830
837
  worker << 1
@@ -72,28 +72,32 @@ class ExceptionTest < MiniTest::Test
72
72
  rescue Exception => e
73
73
  frames << 3
74
74
  raise e
75
- end#.await
76
- 5.times { snooze }
77
- rescue Exception => e
78
- error = e
79
- ensure
80
- assert_kind_of RuntimeError, error
81
- assert_equal [2, 3], frames
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
- spin do
88
+ begin
87
89
  spin do
88
90
  spin do
89
- raise 'foo'
91
+ spin do
92
+ raise 'foo'
93
+ end.await
90
94
  end.await
91
95
  end.await
92
- end.await
93
- rescue Exception => e
94
- error = e
95
- ensure
96
- assert_kind_of RuntimeError, error
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
 
@@ -226,12 +257,10 @@ class SpinLoopTest < MiniTest::Test
226
257
  buffer = []
227
258
  counter = 0
228
259
  t0 = Time.now
229
- f = spin_loop(rate: 10) { buffer << (counter += 1) }
230
- sleep 0.2
260
+ f = spin_loop(rate: 100) { buffer << (counter += 1) }
261
+ sleep 0.02
231
262
  f.stop
232
- elapsed = Time.now - t0
233
- expected = (elapsed * 10).to_i
234
- assert counter >= expected - 1 && counter <= expected + 1
263
+ assert_in_range 1..3, counter
235
264
  end
236
265
  end
237
266
 
@@ -241,22 +270,22 @@ class ThrottledLoopTest < MiniTest::Test
241
270
  counter = 0
242
271
  t0 = Time.now
243
272
  f = spin do
244
- throttled_loop(10) { buffer << (counter += 1) }
273
+ throttled_loop(100) { buffer << (counter += 1) }
245
274
  end
246
- sleep 0.3
247
- f.stop
248
- elapsed = Time.now - t0
249
- expected = (elapsed * 10).to_i
250
- assert counter >= expected - 1 && counter <= expected + 1
275
+ sleep 0.03
276
+ assert_in_range 2..4, counter
251
277
  end
252
278
 
253
279
  def test_throttled_loop_with_count
254
280
  buffer = []
255
281
  counter = 0
282
+ t0 = Time.now
256
283
  f = spin do
257
284
  throttled_loop(50, count: 5) { buffer << (counter += 1) }
258
285
  end
259
286
  f.await
287
+ t1 = Time.now
288
+ assert_in_range 0.075..0.15, t1 - t0
260
289
  assert_equal [1, 2, 3, 4, 5], buffer
261
290
  end
262
291
  end
@@ -275,13 +304,11 @@ class GlobalAPIEtcTest < MiniTest::Test
275
304
  buffer = []
276
305
  t0 = Time.now
277
306
  f = spin do
278
- every(0.1) { buffer << 1 }
307
+ every(0.01) { buffer << 1 }
279
308
  end
280
- sleep 0.5
309
+ sleep 0.05
281
310
  f.stop
282
- elapsed = Time.now - t0
283
- expected = (elapsed / 0.1).to_i
284
- assert buffer.size >= expected - 2 && buffer.size <= expected + 2
311
+ assert_in_range 4..6, buffer.size
285
312
  end
286
313
 
287
314
  def test_sleep
@@ -349,4 +376,4 @@ class GlobalAPIEtcTest < MiniTest::Test
349
376
 
350
377
  assert_equal [0, 1, 2], values
351
378
  end
352
- end
379
+ end