polyphony 0.15 → 0.16

Sign up to get free protection for your applications and to get access to all the features.
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