polyphony 0.15 → 0.16

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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile.lock +11 -3
  4. data/TODO.md +25 -14
  5. data/docs/getting-started/getting-started.md +1 -1
  6. data/docs/getting-started/tutorial.md +2 -0
  7. data/examples/core/cancel.rb +2 -3
  8. data/examples/core/channel_echo.rb +2 -3
  9. data/examples/core/enumerator.rb +2 -3
  10. data/examples/core/fork.rb +2 -2
  11. data/examples/core/genserver.rb +2 -3
  12. data/examples/core/lock.rb +2 -3
  13. data/examples/core/move_on.rb +2 -3
  14. data/examples/core/move_on_twice.rb +2 -3
  15. data/examples/core/move_on_with_ensure.rb +2 -3
  16. data/examples/core/{multiple_async.rb → multiple_spawn.rb} +2 -3
  17. data/examples/core/nested_async.rb +2 -3
  18. data/examples/core/nested_cancel.rb +2 -3
  19. data/examples/core/{nested_multiple_async.rb → nested_multiple_spawn.rb} +2 -3
  20. data/examples/core/next_tick.rb +4 -5
  21. data/examples/core/pulse.rb +2 -3
  22. data/examples/core/resource.rb +2 -3
  23. data/examples/core/resource_cancel.rb +2 -3
  24. data/examples/core/resource_delegate.rb +2 -3
  25. data/examples/core/sleep.rb +2 -3
  26. data/examples/core/sleep_spawn.rb +19 -0
  27. data/examples/core/spawn.rb +2 -3
  28. data/examples/core/spawn_cancel.rb +2 -3
  29. data/examples/core/spawn_error.rb +2 -2
  30. data/examples/core/supervisor.rb +2 -3
  31. data/examples/core/supervisor_with_cancel_scope.rb +2 -3
  32. data/examples/core/supervisor_with_error.rb +2 -3
  33. data/examples/core/supervisor_with_manual_move_on.rb +2 -3
  34. data/examples/core/thread.rb +3 -6
  35. data/examples/core/thread_cancel.rb +2 -5
  36. data/examples/core/thread_pool.rb +3 -6
  37. data/examples/core/throttle.rb +2 -3
  38. data/examples/fs/read.rb +22 -19
  39. data/examples/http/happy_eyeballs.rb +2 -2
  40. data/examples/http/http_client.rb +5 -7
  41. data/examples/http/http_server.rb +2 -3
  42. data/examples/http/http_server_forked.rb +2 -3
  43. data/examples/http/http_server_throttled.rb +2 -3
  44. data/examples/http/http_ws_server.rb +4 -4
  45. data/examples/http/https_raw_client.rb +4 -5
  46. data/examples/http/https_server.rb +2 -3
  47. data/examples/http/https_wss_server.rb +2 -3
  48. data/examples/http/rack_server.rb +2 -4
  49. data/examples/http/rack_server_https.rb +2 -3
  50. data/examples/http/rack_server_https_forked.rb +2 -3
  51. data/examples/http/websocket_secure_server.rb +2 -3
  52. data/examples/http/websocket_server.rb +2 -3
  53. data/examples/interfaces/pg_client.rb +2 -4
  54. data/examples/interfaces/pg_pool.rb +4 -6
  55. data/examples/interfaces/{pg_query.rb → pg_transaction.rb} +2 -4
  56. data/examples/interfaces/redis_channels.rb +2 -4
  57. data/examples/interfaces/redis_client.rb +2 -4
  58. data/examples/interfaces/redis_pubsub.rb +2 -4
  59. data/examples/interfaces/redis_pubsub_perf.rb +2 -4
  60. data/examples/io/echo_client.rb +4 -5
  61. data/examples/io/echo_server.rb +2 -2
  62. data/examples/io/echo_server_with_timeout.rb +3 -5
  63. data/examples/io/echo_stdin.rb +3 -4
  64. data/examples/performance/perf_multi_snooze.rb +2 -2
  65. data/examples/performance/perf_snooze.rb +2 -2
  66. data/examples/performance/thread-vs-fiber/polyphony_server.rb +4 -5
  67. data/ext/ev/ev_module.c +3 -2
  68. data/lib/polyphony/{resource_pool.rb → core/resource_pool.rb} +0 -0
  69. data/lib/polyphony/core/supervisor.rb +8 -8
  70. data/lib/polyphony/extensions/{ssl.rb → openssl.rb} +0 -0
  71. data/lib/polyphony/http/agent.rb +1 -1
  72. data/lib/polyphony/http.rb +12 -4
  73. data/lib/polyphony/net.rb +8 -11
  74. data/lib/polyphony/{extensions/postgres.rb → postgres.rb} +1 -4
  75. data/lib/polyphony/{extensions/redis.rb → redis.rb} +3 -6
  76. data/lib/polyphony/version.rb +1 -1
  77. data/lib/polyphony/websocket.rb +1 -1
  78. data/lib/polyphony.rb +57 -21
  79. data/polyphony.gemspec +5 -4
  80. data/test/test_coprocess.rb +88 -15
  81. data/test/test_core.rb +142 -232
  82. data/test/test_ev.rb +88 -95
  83. data/test/test_io.rb +35 -41
  84. metadata +68 -16
  85. data/examples/core/sleep2.rb +0 -13
  86. data/examples/streams/lines.rb +0 -27
  87. data/examples/streams/stdio.rb +0 -18
  88. data/lib/polyphony/core.rb +0 -45
  89. data/lib/polyphony/server_task.rb +0 -18
data/lib/polyphony.rb CHANGED
@@ -4,37 +4,73 @@ require 'modulation/gem'
4
4
 
5
5
  export_default :Polyphony
6
6
 
7
- Polyphony = import('./polyphony/core')
8
- Exceptions = import('./polyphony/core/exceptions')
9
-
10
- import('polyphony/extensions/socket')
11
- import('polyphony/extensions/ssl')
7
+ require 'fiber'
8
+ require_relative './ev_ext'
9
+ import('./polyphony/extensions/kernel')
10
+ import('./polyphony/extensions/io')
12
11
 
13
12
  module Polyphony
14
- Cancel = Exceptions::Cancel
15
- MoveOn = Exceptions::MoveOn
13
+ exceptions = import('./polyphony/core/exceptions')
14
+ Cancel = exceptions::Cancel
15
+ MoveOn = exceptions::MoveOn
16
+
17
+ Coprocess = import('./polyphony/core/coprocess')
18
+ FiberPool = import('./polyphony/core/fiber_pool')
19
+ Net = import('./polyphony/net')
16
20
 
17
- Net = import('./polyphony/net')
18
21
 
22
+ def self.trap(sig, ref = false, &callback)
23
+ sig = Signal.list[sig.to_s.upcase] if sig.is_a?(Symbol)
24
+ watcher = EV::Signal.new(sig, &callback)
25
+ EV.unref unless ref
26
+ watcher
27
+ end
28
+
29
+ def self.fork(&block)
30
+ EV.break
31
+ pid = Kernel.fork do
32
+ FiberPool.reset!
33
+ EV.post_fork
34
+ Fiber.current.coprocess = Coprocess.new(Fiber.current)
35
+
36
+ block.()
37
+
38
+ # We cannot simply depend on the at_exit block (see below) to yield to the
39
+ # reactor fiber. Doing that will raise a FiberError complaining: "fiber
40
+ # called across stack rewinding barrier". Apparently this is a bug in
41
+ # Ruby, so the workaround is to yield just before exiting.
42
+ suspend
43
+ end
44
+ EV.restart
45
+ pid
46
+ end
47
+
48
+ def self.debug
49
+ @debug
50
+ end
51
+
52
+ def self.debug=(value)
53
+ @debug = value
54
+ end
55
+
19
56
  auto_import(
57
+ CancelScope: './polyphony/core/cancel_scope',
20
58
  Channel: './polyphony/core/channel',
21
- Coprocess: './polyphony/core/coprocess',
59
+ # Coprocess: './polyphony/core/coprocess',
60
+ FS: './polyphony/fs',
61
+ # Net: './polyphony/net',
62
+ ResourcePool: './polyphony/core/resource_pool',
63
+ Supervisor: './polyphony/core/supervisor',
22
64
  Sync: './polyphony/core/sync',
23
65
  Thread: './polyphony/core/thread',
24
66
  ThreadPool: './polyphony/core/thread_pool',
25
-
26
- FS: './polyphony/fs',
27
- # Net: './polyphony/net',
28
- ResourcePool: './polyphony/resource_pool',
29
- Supervisor: './polyphony/supervisor',
30
67
  Websocket: './polyphony/websocket'
31
68
  )
69
+ end
32
70
 
33
- module HTTP
34
- auto_import(
35
- Agent: './polyphony/http/agent',
36
- Rack: './polyphony/http/rack',
37
- Server: './polyphony/http/server',
38
- )
39
- end
71
+ at_exit do
72
+ # in most cases, by the main fiber is done there are still pending or other
73
+ # or asynchronous operations going on. If the reactor loop is not done, we
74
+ # suspend the root fiber until it is done
75
+ suspend if $__reactor_fiber__&.alive?
40
76
  end
data/polyphony.gemspec CHANGED
@@ -17,15 +17,16 @@ Gem::Specification.new do |s|
17
17
  s.extensions = ["ext/ev/extconf.rb"]
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_runtime_dependency 'modulation', '0.23'
20
+ s.add_runtime_dependency 'modulation', '0.24'
21
21
 
22
22
  s.add_runtime_dependency 'http_parser.rb', '0.6.0'
23
23
  s.add_runtime_dependency 'http-2', '0.10.0'
24
24
 
25
- # s.add_runtime_dependency 'hiredis', '0.6.1'
26
- # s.add_runtime_dependency 'pg', '1.0.0'
27
-
28
25
  s.add_development_dependency 'rake-compiler', '1.0.5'
29
26
  s.add_development_dependency 'minitest', '5.11.3'
30
27
  s.add_development_dependency 'localhost', '1.1.4'
28
+ s.add_development_dependency 'websocket', '1.2.8'
29
+ s.add_development_dependency 'pg', '1.1.3'
30
+ s.add_development_dependency 'redis', '4.1.0'
31
+ s.add_development_dependency 'hiredis', '0.6.3'
31
32
  end
@@ -1,49 +1,46 @@
1
1
  require 'minitest/autorun'
2
- require 'modulation'
2
+ require 'bundler/setup'
3
+ require 'polyphony'
3
4
 
4
5
  class CoprocessTest < MiniTest::Test
5
- Core = import('../lib/polyphony/core')
6
- Coprocess = import('../lib/polyphony/core/coprocess')
7
- Exceptions = import('../lib/polyphony/core/exceptions')
8
-
9
6
  def setup
10
7
  EV.rerun
11
8
  end
12
9
 
13
10
  def test_that_main_fiber_has_associated_coprocess
14
- assert_equal(Fiber.current, Coprocess.current.fiber)
15
- assert_equal(Coprocess.current, Fiber.current.coprocess)
11
+ assert_equal(Fiber.current, Polyphony::Coprocess.current.fiber)
12
+ assert_equal(Polyphony::Coprocess.current, Fiber.current.coprocess)
16
13
  end
17
14
 
18
15
  def test_that_new_coprocess_starts_in_suspended_state
19
16
  result = nil
20
- coproc = Coprocess.new { result = 42 }
17
+ coproc = Polyphony::Coprocess.new { result = 42 }
21
18
  assert_nil(result)
22
19
  coproc.await
23
20
  assert_equal(42, result)
24
21
  end
25
22
 
26
23
  def test_that_new_coprocess_runs_on_different_fiber
27
- coproc = Coprocess.new { Fiber.current }
24
+ coproc = Polyphony::Coprocess.new { Fiber.current }
28
25
  fiber = coproc.await
29
26
  assert(fiber != Fiber.current)
30
27
  end
31
28
 
32
29
  def test_that_await_blocks_until_coprocess_is_done
33
30
  result = nil
34
- coproc = Coprocess.new { sleep 0.001; result = 42 }
31
+ coproc = Polyphony::Coprocess.new { sleep 0.001; result = 42 }
35
32
  coproc.await
36
33
  assert_equal(42, result)
37
34
  end
38
35
 
39
36
  def test_that_await_returns_the_coprocess_return_value
40
- coproc = Coprocess.new { [:foo, :bar] }
37
+ coproc = Polyphony::Coprocess.new { [:foo, :bar] }
41
38
  assert_equal([:foo, :bar], coproc.await)
42
39
  end
43
40
 
44
41
  def test_that_await_raises_error_raised_by_coprocess
45
42
  result = nil
46
- coproc = Coprocess.new { raise 'foo' }
43
+ coproc = Polyphony::Coprocess.new { raise 'foo' }
47
44
  begin
48
45
  result = coproc.await
49
46
  rescue => e
@@ -55,7 +52,7 @@ class CoprocessTest < MiniTest::Test
55
52
 
56
53
  def test_that_running_coprocess_can_be_cancelled
57
54
  result = []
58
- coproc = Coprocess.new {
55
+ coproc = Polyphony::Coprocess.new {
59
56
  result << 1
60
57
  sleep 0.002
61
58
  result << 2
@@ -68,13 +65,13 @@ class CoprocessTest < MiniTest::Test
68
65
  end
69
66
  assert_equal(2, result.size)
70
67
  assert_equal(1, result[0])
71
- assert_kind_of(Exceptions::Cancel, result[1])
68
+ assert_kind_of(Polyphony::Cancel, result[1])
72
69
  end
73
70
 
74
71
  def test_that_running_coprocess_can_be_interrupted
75
72
  # that is, stopped without exception
76
73
  result = []
77
- coproc = Coprocess.new {
74
+ coproc = Polyphony::Coprocess.new {
78
75
  result << 1
79
76
  sleep 0.002
80
77
  result << 2
@@ -86,6 +83,82 @@ class CoprocessTest < MiniTest::Test
86
83
  assert_equal(1, result.size)
87
84
  assert_equal(42, await_result)
88
85
  end
86
+
87
+ def test_that_coprocess_can_be_awaited
88
+ result = nil
89
+ spawn do
90
+ coprocess = Polyphony::Coprocess.new { sleep(0.001); 42 }
91
+ result = coprocess.await
92
+ end
93
+ suspend
94
+ assert_equal(42, result)
95
+ end
96
+
97
+ def test_that_coprocess_can_be_stopped
98
+ result = nil
99
+ coprocess = spawn do
100
+ sleep(0.001)
101
+ result = 42
102
+ end
103
+ EV.next_tick { coprocess.interrupt }
104
+ suspend
105
+ assert_nil(result)
106
+ end
107
+
108
+ def test_that_coprocess_can_be_cancelled
109
+ result = nil
110
+ coprocess = spawn do
111
+ sleep(0.001)
112
+ result = 42
113
+ rescue Polyphony::Cancel => e
114
+ result = e
115
+ end
116
+ EV.next_tick { coprocess.cancel! }
117
+
118
+ suspend
119
+
120
+ assert_kind_of(Polyphony::Cancel, result)
121
+ assert_kind_of(Polyphony::Cancel, coprocess.result)
122
+ assert_nil(coprocess.running?)
123
+ end
124
+
125
+ def test_that_inner_coprocess_can_be_interrupted
126
+ result = nil
127
+ coprocess2 = nil
128
+ coprocess = spawn do
129
+ coprocess2 = spawn do
130
+ sleep(0.001)
131
+ result = 42
132
+ end
133
+ coprocess2.await
134
+ result && result += 1
135
+ end
136
+ EV.next_tick { coprocess.interrupt }
137
+ suspend
138
+ assert_nil(result)
139
+ assert_nil(coprocess.running?)
140
+ assert_nil(coprocess2.running?)
141
+ end
142
+
143
+ def test_that_inner_coprocess_can_interrupt_outer_coprocess
144
+ result, coprocess2 = nil
145
+
146
+ coprocess = spawn do
147
+ coprocess2 = spawn do
148
+ EV.next_tick { coprocess.interrupt }
149
+ sleep(0.001)
150
+ result = 42
151
+ end
152
+ coprocess2.await
153
+ result && result += 1
154
+ end
155
+
156
+ suspend
157
+
158
+ assert_nil(result)
159
+ assert_nil(coprocess.running?)
160
+ assert_nil(coprocess2.running?)
161
+ end
89
162
  end
90
163
 
91
164
  class MailboxTest < MiniTest::Test
data/test/test_core.rb CHANGED
@@ -1,274 +1,184 @@
1
1
  require 'minitest/autorun'
2
- require 'modulation'
2
+ require 'bundler/setup'
3
+ require 'polyphony'
3
4
 
4
- module CoreTests
5
- CancelScope = import('../lib/polyphony/core/cancel_scope')
6
- Core = import('../lib/polyphony/core')
7
- Coprocess = import('../lib/polyphony/core/coprocess')
8
- Exceptions = import('../lib/polyphony/core/exceptions')
9
- Supervisor = import('../lib/polyphony/core/supervisor')
10
-
11
- class SpawnTest < MiniTest::Test
12
- def setup
13
- EV.rerun
14
- end
15
-
16
- def test_that_spawn_returns_a_coprocess
17
- result = nil
18
- coprocess = spawn { result = 42 }
19
-
20
- assert_kind_of(Coprocess, coprocess)
21
- assert_nil(result)
22
- suspend
23
- assert_equal(42, result)
24
- end
25
-
26
- def test_that_spawn_accepts_coprocess_argument
27
- result = nil
28
- coprocess = Coprocess.new { result = 42 }
29
- spawn coprocess
30
-
31
- assert_nil(result)
32
- suspend
33
- assert_equal(42, result)
34
- end
35
-
36
- def test_that_spawned_coprocess_saves_result
37
- coprocess = spawn { 42 }
38
-
39
- assert_kind_of(Coprocess, coprocess)
40
- assert_nil(coprocess.result)
41
- suspend
42
- assert_equal(42, coprocess.result)
43
- end
44
-
45
- def test_that_spawned_coprocess_can_be_interrupted
46
- result = nil
47
- coprocess = spawn { sleep(1); 42 }
48
- EV.next_tick { coprocess.interrupt }
49
- suspend
50
- assert_nil(coprocess.result)
51
- end
5
+ class SpawnTest < MiniTest::Test
6
+ def setup
7
+ EV.rerun
52
8
  end
53
9
 
54
- class CoprocessTest < MiniTest::Test
55
- def setup
56
- EV.rerun
57
- end
10
+ def test_that_spawn_returns_a_coprocess
11
+ result = nil
12
+ coprocess = spawn { result = 42 }
58
13
 
59
- def test_that_coprocess_can_be_awaited
60
- result = nil
61
- spawn do
62
- coprocess = Coprocess.new { sleep(0.001); 42 }
63
- result = coprocess.await
64
- end
65
- suspend
66
- assert_equal(42, result)
67
- end
14
+ assert_kind_of(Polyphony::Coprocess, coprocess)
15
+ assert_nil(result)
16
+ suspend
17
+ assert_equal(42, result)
18
+ end
68
19
 
69
- def test_that_coprocess_can_be_stopped
70
- result = nil
71
- coprocess = spawn do
72
- sleep(0.001)
73
- result = 42
74
- end
75
- EV.next_tick { coprocess.interrupt }
76
- suspend
77
- assert_nil(result)
78
- end
20
+ def test_that_spawn_accepts_coprocess_argument
21
+ result = nil
22
+ coprocess = Polyphony::Coprocess.new { result = 42 }
23
+ spawn coprocess
79
24
 
80
- def test_that_coprocess_can_be_cancelled
81
- result = nil
82
- coprocess = spawn do
83
- sleep(0.001)
84
- result = 42
85
- rescue Exceptions::Cancel => e
86
- result = e
87
- end
88
- EV.next_tick { coprocess.cancel! }
25
+ assert_nil(result)
26
+ suspend
27
+ assert_equal(42, result)
28
+ end
89
29
 
90
- suspend
30
+ def test_that_spawned_coprocess_saves_result
31
+ coprocess = spawn { 42 }
91
32
 
92
- assert_kind_of(Exceptions::Cancel, result)
93
- assert_kind_of(Exceptions::Cancel, coprocess.result)
94
- assert_nil(coprocess.running?)
95
- end
33
+ assert_kind_of(Polyphony::Coprocess, coprocess)
34
+ assert_nil(coprocess.result)
35
+ suspend
36
+ assert_equal(42, coprocess.result)
37
+ end
96
38
 
97
- def test_that_inner_coprocess_can_be_interrupted
98
- result = nil
99
- coprocess2 = nil
100
- coprocess = spawn do
101
- coprocess2 = spawn do
102
- sleep(0.001)
103
- result = 42
104
- end
105
- coprocess2.await
106
- result && result += 1
107
- end
108
- EV.next_tick { coprocess.interrupt }
109
- suspend
110
- assert_nil(result)
111
- assert_nil(coprocess.running?)
112
- assert_nil(coprocess2.running?)
113
- end
39
+ def test_that_spawned_coprocess_can_be_interrupted
40
+ result = nil
41
+ coprocess = spawn { sleep(1); 42 }
42
+ EV.next_tick { coprocess.interrupt }
43
+ suspend
44
+ assert_nil(coprocess.result)
45
+ end
46
+ end
114
47
 
115
- def test_that_inner_coprocess_can_interrupt_outer_coprocess
116
- result, coprocess2 = nil
117
-
118
- coprocess = spawn do
119
- coprocess2 = spawn do
120
- EV.next_tick { coprocess.interrupt }
121
- sleep(0.001)
122
- result = 42
123
- end
124
- coprocess2.await
125
- result && result += 1
126
- end
127
-
128
- suspend
129
-
130
- assert_nil(result)
131
- assert_nil(coprocess.running?)
132
- assert_nil(coprocess2.running?)
133
- end
48
+ class CancelScopeTest < Minitest::Test
49
+ def setup
50
+ EV.rerun
134
51
  end
135
52
 
136
- class CancelScopeTest < Minitest::Test
137
- def setup
138
- EV.rerun
53
+ def sleep_with_cancel(ctx, mode = nil)
54
+ Polyphony::CancelScope.new(mode: mode).call do |c|
55
+ ctx[:cancel_scope] = c
56
+ ctx[:result] = sleep(0.01)
139
57
  end
58
+ end
140
59
 
141
- def sleep_with_cancel(ctx, mode = nil)
142
- CancelScope.new(mode: mode).call do |c|
143
- ctx[:cancel_scope] = c
144
- ctx[:result] = sleep(0.01)
145
- end
146
- end
60
+ def test_that_cancel_scope_cancels_coprocess
61
+ ctx = {}
62
+ spawn do
63
+ EV::Timer.new(0.005, 0).start { ctx[:cancel_scope]&.cancel! }
64
+ sleep_with_cancel(ctx, :cancel)
65
+ rescue Exception => e
66
+ ctx[:result] = e
67
+ end
68
+ assert_nil(ctx[:result])
69
+ # async operation will only begin on next iteration of event loop
70
+ assert_nil(ctx[:cancel_scope])
71
+
72
+ suspend
73
+ assert_kind_of(Polyphony::CancelScope, ctx[:cancel_scope])
74
+ assert_kind_of(Polyphony::Cancel, ctx[:result])
75
+ end
147
76
 
148
- def test_that_cancel_scope_cancels_coprocess
149
- ctx = {}
150
- spawn do
151
- EV::Timer.new(0.005, 0).start { ctx[:cancel_scope]&.cancel! }
152
- sleep_with_cancel(ctx, :cancel)
153
- rescue Exception => e
154
- ctx[:result] = e
77
+ # def test_that_cancel_scope_cancels_async_op_with_stop
78
+ # ctx = {}
79
+ # spawn do
80
+ # EV::Timer.new(0, 0).start { ctx[:cancel_scope].cancel! }
81
+ # sleep_with_cancel(ctx, :stop)
82
+ # end
83
+
84
+ # suspend
85
+ # assert(ctx[:cancel_scope])
86
+ # assert_nil(ctx[:result])
87
+ # end
88
+
89
+ def test_that_cancel_after_raises_cancelled_exception
90
+ result = nil
91
+ spawn do
92
+ cancel_after(0.01) do
93
+ sleep(1000)
155
94
  end
156
- assert_nil(ctx[:result])
157
- # async operation will only begin on next iteration of event loop
158
- assert_nil(ctx[:cancel_scope])
159
-
160
- suspend
161
- assert_kind_of(CancelScope, ctx[:cancel_scope])
162
- assert_kind_of(Exceptions::Cancel, ctx[:result])
95
+ result = 42
96
+ rescue Polyphony::Cancel
97
+ result = :cancelled
163
98
  end
99
+ suspend
100
+ assert_equal(:cancelled, result)
101
+ end
164
102
 
165
- # def test_that_cancel_scope_cancels_async_op_with_stop
166
- # ctx = {}
167
- # spawn do
168
- # EV::Timer.new(0, 0).start { ctx[:cancel_scope].cancel! }
169
- # sleep_with_cancel(ctx, :stop)
170
- # end
171
-
172
- # suspend
173
- # assert(ctx[:cancel_scope])
174
- # assert_nil(ctx[:result])
175
- # end
176
-
177
- def test_that_cancel_after_raises_cancelled_exception
178
- result = nil
179
- spawn do
180
- cancel_after(0.01) do
103
+ def test_that_cancel_scopes_can_be_nested
104
+ inner_result = nil
105
+ outer_result = nil
106
+ spawn do
107
+ move_on_after(0.01) do
108
+ move_on_after(0.02) do
181
109
  sleep(1000)
182
110
  end
183
- result = 42
184
- rescue Exceptions::Cancel
185
- result = :cancelled
111
+ inner_result = 42
186
112
  end
187
- suspend
188
- assert_equal(:cancelled, result)
113
+ outer_result = 42
189
114
  end
115
+ suspend
116
+ assert_nil(inner_result)
117
+ assert_equal(42, outer_result)
190
118
 
191
- def test_that_cancel_scopes_can_be_nested
192
- inner_result = nil
193
- outer_result = nil
194
- spawn do
195
- move_on_after(0.01) do
196
- move_on_after(0.02) do
197
- sleep(1000)
198
- end
199
- inner_result = 42
200
- end
201
- outer_result = 42
202
- end
203
- suspend
204
- assert_nil(inner_result)
205
- assert_equal(42, outer_result)
206
-
207
- EV.rerun
119
+ EV.rerun
208
120
 
209
- outer_result = nil
210
- spawn do
211
- move_on_after(0.02) do
212
- move_on_after(0.01) do
213
- sleep(1000)
214
- end
215
- inner_result = 42
121
+ outer_result = nil
122
+ spawn do
123
+ move_on_after(0.02) do
124
+ move_on_after(0.01) do
125
+ sleep(1000)
216
126
  end
217
- outer_result = 42
127
+ inner_result = 42
218
128
  end
219
- suspend
220
- assert_equal(42, inner_result)
221
- assert_equal(42, outer_result)
129
+ outer_result = 42
222
130
  end
131
+ suspend
132
+ assert_equal(42, inner_result)
133
+ assert_equal(42, outer_result)
223
134
  end
135
+ end
224
136
 
225
- class SupervisorTest < MiniTest::Test
226
- def setup
227
- EV.rerun
228
- end
137
+ class SupervisorTest < MiniTest::Test
138
+ def setup
139
+ EV.rerun
140
+ end
229
141
 
230
- def sleep_and_set(ctx, idx)
231
- proc do
232
- sleep(0.001 * idx)
233
- ctx[idx] = true
234
- end
142
+ def sleep_and_set(ctx, idx)
143
+ proc do
144
+ sleep(0.001 * idx)
145
+ ctx[idx] = true
235
146
  end
147
+ end
236
148
 
237
- def parallel_sleep(ctx)
238
- supervise do |s|
239
- (1..3).each { |idx| s.spawn sleep_and_set(ctx, idx) }
240
- end
241
- end
242
-
243
- def test_that_supervisor_waits_for_all_nested_coprocesss_to_complete
244
- ctx = {}
245
- spawn do
246
- parallel_sleep(ctx)
247
- end
248
- suspend
249
- assert(ctx[1])
250
- assert(ctx[2])
251
- assert(ctx[3])
149
+ def parallel_sleep(ctx)
150
+ supervise do |s|
151
+ (1..3).each { |idx| s.spawn sleep_and_set(ctx, idx) }
252
152
  end
153
+ end
154
+
155
+ def test_that_supervisor_waits_for_all_nested_coprocesses_to_complete
156
+ ctx = {}
157
+ spawn do
158
+ parallel_sleep(ctx)
159
+ end
160
+ suspend
161
+ assert(ctx[1])
162
+ assert(ctx[2])
163
+ assert(ctx[3])
164
+ end
253
165
 
254
- def test_that_supervisor_can_add_coprocesss_after_having_started
255
- result = []
256
- spawn do
257
- supervisor = Supervisor.new
258
- 3.times do |i|
259
- spawn do
166
+ def test_that_supervisor_can_add_coprocesses_after_having_started
167
+ result = []
168
+ spawn {
169
+ supervisor = Polyphony::Supervisor.new
170
+ 3.times do |i|
171
+ spawn do
172
+ sleep(0.001)
173
+ supervisor.spawn do
260
174
  sleep(0.001)
261
- supervisor.spawn do
262
- sleep(0.001)
263
- result << i
264
- end
175
+ result << i
265
176
  end
266
177
  end
267
- supervisor.await
268
178
  end
179
+ supervisor.await
180
+ }.await
269
181
 
270
- suspend
271
- assert_equal([0, 1, 2], result)
272
- end
182
+ assert_equal([0, 1, 2], result)
273
183
  end
274
184
  end