concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/lib/concurrent.rb +9 -29
  4. data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
  5. data/lib/concurrent/actor/actor_context.rb +77 -0
  6. data/lib/concurrent/actor/actor_ref.rb +67 -0
  7. data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
  8. data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
  9. data/lib/concurrent/actors.rb +5 -0
  10. data/lib/concurrent/agent.rb +81 -47
  11. data/lib/concurrent/async.rb +35 -35
  12. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  13. data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
  14. data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
  15. data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
  16. data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
  17. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  18. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  19. data/lib/concurrent/atomic/event.rb +103 -0
  20. data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
  21. data/lib/concurrent/atomics.rb +9 -0
  22. data/lib/concurrent/channel/buffered_channel.rb +6 -4
  23. data/lib/concurrent/channel/channel.rb +30 -2
  24. data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
  25. data/lib/concurrent/channel/waitable_list.rb +3 -1
  26. data/lib/concurrent/channels.rb +5 -0
  27. data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
  28. data/lib/concurrent/collection/priority_queue.rb +305 -0
  29. data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
  30. data/lib/concurrent/collections.rb +3 -0
  31. data/lib/concurrent/configuration.rb +68 -19
  32. data/lib/concurrent/dataflow.rb +9 -9
  33. data/lib/concurrent/delay.rb +21 -13
  34. data/lib/concurrent/dereferenceable.rb +40 -33
  35. data/lib/concurrent/exchanger.rb +3 -0
  36. data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
  37. data/lib/concurrent/executor/executor.rb +222 -0
  38. data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
  39. data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
  40. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  41. data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
  42. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  43. data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
  44. data/lib/concurrent/executor/one_by_one.rb +65 -0
  45. data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
  46. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  47. data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
  48. data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
  49. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
  50. data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
  51. data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
  52. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  53. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  54. data/lib/concurrent/executor/timer_set.rb +138 -0
  55. data/lib/concurrent/executors.rb +9 -0
  56. data/lib/concurrent/future.rb +39 -40
  57. data/lib/concurrent/ivar.rb +22 -15
  58. data/lib/concurrent/mvar.rb +2 -1
  59. data/lib/concurrent/obligation.rb +9 -3
  60. data/lib/concurrent/observable.rb +33 -0
  61. data/lib/concurrent/options_parser.rb +46 -0
  62. data/lib/concurrent/promise.rb +23 -24
  63. data/lib/concurrent/scheduled_task.rb +21 -45
  64. data/lib/concurrent/timer_task.rb +204 -126
  65. data/lib/concurrent/tvar.rb +1 -1
  66. data/lib/concurrent/utilities.rb +3 -36
  67. data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
  68. data/lib/concurrent/utility/timeout.rb +36 -0
  69. data/lib/concurrent/utility/timer.rb +21 -0
  70. data/lib/concurrent/version.rb +1 -1
  71. data/lib/concurrent_ruby_ext.bundle +0 -0
  72. data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
  73. data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
  74. data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
  75. data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
  76. data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
  77. data/spec/concurrent/agent_spec.rb +160 -71
  78. data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
  79. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
  80. data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
  81. data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
  82. data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
  83. data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
  84. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
  85. data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
  86. data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
  87. data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
  88. data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
  89. data/spec/concurrent/channel/channel_spec.rb +6 -4
  90. data/spec/concurrent/channel/probe_spec.rb +37 -9
  91. data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
  92. data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
  93. data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
  94. data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
  95. data/spec/concurrent/configuration_spec.rb +4 -70
  96. data/spec/concurrent/dereferenceable_shared.rb +5 -4
  97. data/spec/concurrent/exchanger_spec.rb +10 -5
  98. data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
  99. data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
  100. data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
  101. data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
  102. data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
  103. data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
  104. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
  105. data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
  106. data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
  107. data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
  108. data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
  109. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
  110. data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
  111. data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
  112. data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
  113. data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
  114. data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
  115. data/spec/concurrent/executor/timer_set_spec.rb +183 -0
  116. data/spec/concurrent/future_spec.rb +12 -0
  117. data/spec/concurrent/ivar_spec.rb +11 -1
  118. data/spec/concurrent/observable_shared.rb +173 -0
  119. data/spec/concurrent/observable_spec.rb +51 -0
  120. data/spec/concurrent/options_parser_spec.rb +71 -0
  121. data/spec/concurrent/runnable_shared.rb +6 -0
  122. data/spec/concurrent/scheduled_task_spec.rb +60 -40
  123. data/spec/concurrent/timer_task_spec.rb +130 -144
  124. data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
  125. data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
  126. data/spec/concurrent/utility/timer_spec.rb +52 -0
  127. metadata +147 -108
  128. data/lib/concurrent/actor_context.rb +0 -31
  129. data/lib/concurrent/actor_ref.rb +0 -39
  130. data/lib/concurrent/atomic.rb +0 -121
  131. data/lib/concurrent/channel/probe.rb +0 -19
  132. data/lib/concurrent/count_down_latch.rb +0 -60
  133. data/lib/concurrent/event.rb +0 -80
  134. data/lib/concurrent/java_cached_thread_pool.rb +0 -45
  135. data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
  136. data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
  137. data/lib/concurrent/simple_actor_ref.rb +0 -124
  138. data/lib/concurrent/thread_pool_executor.rb +0 -30
  139. data/spec/concurrent/atomic_spec.rb +0 -201
  140. data/spec/concurrent/count_down_latch_spec.rb +0 -125
  141. data/spec/concurrent/safe_task_executor_spec.rb +0 -58
  142. data/spec/concurrent/simple_actor_ref_spec.rb +0 -219
@@ -1,6 +1,6 @@
1
1
  require 'set'
2
2
 
3
- require 'concurrent/thread_local_var'
3
+ require 'concurrent/atomic/thread_local_var'
4
4
 
5
5
  module Concurrent
6
6
 
@@ -1,36 +1,3 @@
1
- require 'rbconfig'
2
- require 'thread'
3
-
4
- module Concurrent
5
-
6
- # Error raised when an operations times out.
7
- TimeoutError = Class.new(StandardError)
8
-
9
- # Wait the given number of seconds for the block operation to complete.
10
- #
11
- # @param [Integer] seconds The number of seconds to wait
12
- #
13
- # @return The result of the block operation
14
- #
15
- # @raise Concurrent::TimeoutError when the block operation does not complete
16
- # in the allotted number of seconds.
17
- #
18
- # @note This method is intended to be a simpler and more reliable replacement
19
- # to the Ruby standard library +Timeout::timeout+ method.
20
- def timeout(seconds)
21
-
22
- thread = Thread.new do
23
- Thread.current[:result] = yield
24
- end
25
- success = thread.join(seconds)
26
-
27
- if success
28
- return thread[:result]
29
- else
30
- raise TimeoutError
31
- end
32
- ensure
33
- Thread.kill(thread) unless thread.nil?
34
- end
35
- module_function :timeout
36
- end
1
+ require 'concurrent/utility/processor_count'
2
+ require 'concurrent/utility/timeout'
3
+ require 'concurrent/utility/timer'
@@ -5,7 +5,7 @@ module Concurrent
5
5
  # Number of processors seen by the OS and used for process scheduling. For performance
6
6
  # reasons the calculated value will be memoized on the first call.
7
7
  #
8
- # When running under JRuby the Java runtime call +java.lang.Runtime.getRuntime.availableProcessors+
8
+ # When running under JRuby the Java runtime call `java.lang.Runtime.getRuntime.availableProcessors`
9
9
  # will be used. According to the Java documentation this "value may change
10
10
  # during a particular invocation of the virtual machine... [applications]
11
11
  # should therefore occasionally poll this property." Subsequently the result
@@ -0,0 +1,36 @@
1
+ require 'rbconfig'
2
+ require 'thread'
3
+
4
+ module Concurrent
5
+
6
+ # Error raised when an operations times out.
7
+ TimeoutError = Class.new(StandardError)
8
+
9
+ # Wait the given number of seconds for the block operation to complete.
10
+ #
11
+ # @param [Integer] seconds The number of seconds to wait
12
+ #
13
+ # @return The result of the block operation
14
+ #
15
+ # @raise Concurrent::TimeoutError when the block operation does not complete
16
+ # in the allotted number of seconds.
17
+ #
18
+ # @note This method is intended to be a simpler and more reliable replacement
19
+ # to the Ruby standard library `Timeout::timeout` method.
20
+ def timeout(seconds)
21
+
22
+ thread = Thread.new do
23
+ Thread.current[:result] = yield
24
+ end
25
+ success = thread.join(seconds)
26
+
27
+ if success
28
+ return thread[:result]
29
+ else
30
+ raise TimeoutError
31
+ end
32
+ ensure
33
+ Thread.kill(thread) unless thread.nil?
34
+ end
35
+ module_function :timeout
36
+ end
@@ -0,0 +1,21 @@
1
+ require 'concurrent/configuration'
2
+ require 'thread'
3
+
4
+ module Concurrent
5
+
6
+ # Perform the given operation asynchronously after the given number of seconds.
7
+ #
8
+ # @param [Fixnum] seconds the interval in seconds to wait before executing the task
9
+ #
10
+ # @yield the task to execute
11
+ #
12
+ # @return [Boolean] true
13
+ def timer(seconds, *args, &block)
14
+ raise ArgumentError.new('no block given') unless block_given?
15
+ raise ArgumentError.new('interval must be greater than or equal to zero') if seconds < 0
16
+
17
+ Concurrent.configuration.global_timer_set.post(seconds, *args, &block)
18
+ true
19
+ end
20
+ module_function :timer
21
+ end
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '0.6.0.pre.1'
2
+ VERSION = '0.6.0.pre.2'
3
3
  end
@@ -10,20 +10,12 @@ module Concurrent
10
10
  end
11
11
  end
12
12
 
13
- it 'protects #initialize' do
14
- expect {
15
- described_class.new
16
- }.to raise_error(NoMethodError)
17
- end
18
-
19
13
  context 'callbacks' do
20
14
 
21
15
  subject { described_class.send(:new) }
22
16
 
23
17
  specify { subject.should respond_to :on_start }
24
18
 
25
- specify { subject.should respond_to :on_reset }
26
-
27
19
  specify { subject.should respond_to :on_shutdown }
28
20
  end
29
21
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- def shared_actor_test_class
3
+ def create_actor_test_class
4
4
  Class.new do
5
5
  include Concurrent::ActorContext
6
6
 
@@ -33,6 +33,10 @@ end
33
33
 
34
34
  share_examples_for :actor_ref do
35
35
 
36
+ after(:each) do
37
+ subject.shutdown
38
+ end
39
+
36
40
  it 'includes ActorRef' do
37
41
  subject.should be_a Concurrent::ActorRef
38
42
  end
@@ -95,7 +99,9 @@ share_examples_for :actor_ref do
95
99
  end
96
100
 
97
101
  it 'returns self' do
98
- (subject << [1,2,3,4]).should eq subject
102
+ expected = subject
103
+ result = subject << [1,2,3,4]
104
+ result.should eq expected
99
105
  end
100
106
  end
101
107
 
@@ -158,10 +164,7 @@ share_examples_for :actor_ref do
158
164
 
159
165
  it 'blocks forever when the timeout is nil' do
160
166
  start = Time.now.to_f
161
- begin
162
- subject.post!(nil, :sleep, 1)
163
- rescue
164
- end
167
+ subject.post!(nil, :sleep, 1)
165
168
  delta = Time.now.to_f - start
166
169
  delta.should > 1
167
170
  end
@@ -257,57 +260,4 @@ share_examples_for :actor_ref do
257
260
  sleep(0.1)
258
261
  end
259
262
  end
260
-
261
- context 'observation' do
262
-
263
- let(:observer_class) do
264
- Class.new do
265
- attr_reader :time, :msg, :value, :reason
266
- def update(time, msg, value, reason)
267
- @msg = msg
268
- @time = time
269
- @value = value
270
- @reason = reason
271
- end
272
- end
273
- end
274
-
275
- it 'notifies observers' do
276
- o1 = observer_class.new
277
- o2 = observer_class.new
278
-
279
- subject.add_observer(o1)
280
- subject.add_observer(o2)
281
-
282
- subject << :foo
283
- sleep(0.1)
284
-
285
- o1.value.should eq :foo
286
- o1.reason.should be_nil
287
-
288
- o2.value.should eq :foo
289
- o2.reason.should be_nil
290
- end
291
-
292
- it 'does not notify removed observers' do
293
- o1 = observer_class.new
294
- o2 = observer_class.new
295
-
296
- subject.add_observer(o1)
297
- subject.add_observer(o2)
298
-
299
- subject << :foo
300
- sleep(0.1)
301
-
302
- subject.delete_observer(o1)
303
- subject << :bar
304
- sleep(0.1)
305
- o1.value.should_not eq :bar
306
-
307
- subject.delete_observers
308
- subject << :baz
309
- sleep(0.1)
310
- o1.value.should_not eq :baz
311
- end
312
- end
313
263
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require_relative 'postable_shared'
3
- require_relative 'runnable_shared'
3
+ require_relative '../runnable_shared'
4
4
 
5
5
  module Concurrent
6
6
 
@@ -90,15 +90,16 @@ module Concurrent
90
90
 
91
91
  context 'exception handling' do
92
92
 
93
- it 'supresses exceptions thrown when handling messages' do
94
- actor = actor_class.new{|msg| raise StandardError }
95
- @thread = Thread.new{ actor.run }
96
- expect {
97
- @thread.join(0.1)
98
- 10.times { actor.post(true) }
99
- }.not_to raise_error
100
- actor.stop
101
- end
93
+ #it 'supresses exceptions thrown when handling messages' do
94
+ #pending('intermittently failing; deprecated')
95
+ #actor = actor_class.new{|msg| raise StandardError }
96
+ #@thread = Thread.new{ actor.run }
97
+ #expect {
98
+ #@thread.join(0.1)
99
+ #10.times { actor.post(true) }
100
+ #}.not_to raise_error
101
+ #actor.stop
102
+ #end
102
103
  end
103
104
 
104
105
  context 'observation' do
@@ -132,25 +133,26 @@ module Concurrent
132
133
  }.new
133
134
  end
134
135
 
135
- it 'notifies observers when a message is successfully handled' do
136
- pending('intermittently failing; deprecated')
137
- observer.should_receive(:update).exactly(10).times.with(any_args())
138
- subject.add_observer(observer)
139
- @thread = Thread.new{ subject.run }
140
- @thread.join(0.1)
141
- 10.times { subject.post(42) }
142
- @thread.join(0.1)
143
- end
144
-
145
- it 'notifies observers when a message raises an exception' do
146
- error = StandardError.new
147
- observer.should_receive(:update).exactly(10).times.with(any_args())
148
- subject.add_observer(observer)
149
- @thread = Thread.new{ subject.run }
150
- @thread.join(0.1)
151
- 10.times { subject.post(error) }
152
- @thread.join(0.1)
153
- end
136
+ #it 'notifies observers when a message is successfully handled' do
137
+ #pending('intermittently failing; deprecated')
138
+ #observer.should_receive(:update).exactly(10).times.with(any_args())
139
+ #subject.add_observer(observer)
140
+ #@thread = Thread.new{ subject.run }
141
+ #@thread.join(0.1)
142
+ #10.times { subject.post(42) }
143
+ #@thread.join(0.1)
144
+ #end
145
+
146
+ #it 'notifies observers when a message raises an exception' do
147
+ #pending('intermittently failing; deprecated')
148
+ #error = StandardError.new
149
+ #observer.should_receive(:update).exactly(10).times.with(any_args())
150
+ #subject.add_observer(observer)
151
+ #@thread = Thread.new{ subject.run }
152
+ #@thread.join(0.1)
153
+ #10.times { subject.post(error) }
154
+ #@thread.join(0.1)
155
+ #end
154
156
 
155
157
  it 'passes the time, message, value, and reason to the observer on success' do
156
158
  subject.add_observer(observer)
@@ -243,18 +245,18 @@ module Concurrent
243
245
  @thread.kill
244
246
  end
245
247
 
246
- it 'posts to the mailbox with Poolbox#<<' do
247
- pending('intermittently failing; deprecated')
248
- @expected = false
249
- mailbox, pool = clazz.pool(1)
250
- @thread = Thread.new{ pool.first.run }
251
- sleep(0.1)
252
- mailbox << 42
253
- sleep(0.1)
254
- pool.first.last_message.should eq [42]
255
- pool.first.stop
256
- @thread.kill
257
- end
248
+ #it 'posts to the mailbox with Poolbox#<<' do
249
+ #pending('intermittently failing; deprecated')
250
+ #@expected = false
251
+ #mailbox, pool = clazz.pool(1)
252
+ #@thread = Thread.new{ pool.first.run }
253
+ #sleep(0.1)
254
+ #mailbox << 42
255
+ #sleep(0.1)
256
+ #pool.first.last_message.should eq [42]
257
+ #pool.first.stop
258
+ #@thread.kill
259
+ #end
258
260
  end
259
261
 
260
262
  context 'subclassing' do
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+ require_relative 'actor_ref_shared'
3
+
4
+ module Concurrent
5
+
6
+ describe SimpleActorRef do
7
+
8
+ after(:each) do
9
+ subject.shutdown
10
+ sleep(0.1)
11
+ end
12
+
13
+ subject do
14
+ create_actor_test_class.spawn
15
+ end
16
+
17
+ it_should_behave_like :actor_ref
18
+
19
+ context 'construction' do
20
+
21
+ it 'supports :args being nil' do
22
+ subject = create_actor_test_class.spawn
23
+ actor = subject.instance_variable_get(:@actor)
24
+ actor.argv.should be_empty
25
+ end
26
+
27
+ it 'passes all :args option to the actor constructor' do
28
+ subject = create_actor_test_class.spawn(args: [1, 2, 3, 4])
29
+ actor = subject.instance_variable_get(:@actor)
30
+ actor.argv.should eq [1, 2, 3, 4]
31
+ end
32
+
33
+ it 'passes the options hash to the ActorRef constructor' do
34
+ subject # prevent the after(:all) block from breaking this test
35
+ opts = {foo: :bar, hello: :world}
36
+ described_class.should_receive(:new).once.with(anything, opts)
37
+ create_actor_test_class.spawn(opts)
38
+ end
39
+
40
+ it 'calls #on_start on the actor' do
41
+ actor = double(:create_actor_test_class)
42
+ actor.should_receive(:on_start).once.with(no_args)
43
+ SimpleActorRef.new(actor)
44
+ end
45
+ end
46
+
47
+ context 'reset_on_error' do
48
+
49
+ it 'creates a new actor on exception when true' do
50
+ clazz = create_actor_test_class
51
+ args = [:foo, :bar, :hello, :world]
52
+ ref = clazz.spawn(reset_on_error: true, args: args)
53
+ clazz.should_receive(:new).once.with(*args)
54
+ ref.post(:poison)
55
+ end
56
+
57
+ it 'does not create a new actor on exception when false' do
58
+ clazz = create_actor_test_class
59
+ args = [:foo, :bar, :hello, :world]
60
+ ref = clazz.spawn(reset_on_error: true, args: args)
61
+ clazz.should_not_receive(:new).with(any_args)
62
+ ref.post(:poison)
63
+ end
64
+
65
+ it 'defaults to true' do
66
+ clazz = create_actor_test_class
67
+ args = [:foo, :bar, :hello, :world]
68
+ ref = clazz.spawn(args: args)
69
+ clazz.should_receive(:new).once.with(*args)
70
+ ref.post(:poison)
71
+ end
72
+ end
73
+
74
+ context 'rescue_exception' do
75
+
76
+ after(:each) do
77
+ @ref.shutdown if @ref
78
+ end
79
+
80
+ it 'rescues Exception in the actor thread when true' do
81
+ @ref = create_actor_test_class.spawn(
82
+ abort_on_exception: false,
83
+ rescue_exception: true
84
+ )
85
+
86
+ ivar = @ref.post(:poison)
87
+ sleep(0.1)
88
+ ivar.reason.should be_a StandardError
89
+
90
+ ivar = @ref.post(:bullet)
91
+ sleep(0.1)
92
+ ivar.reason.should be_a Exception
93
+ end
94
+
95
+ it 'rescues StandardError in the actor thread when false' do
96
+ @ref = create_actor_test_class.spawn(
97
+ abort_on_exception: false,
98
+ rescue_exception: false
99
+ )
100
+
101
+ ivar = @ref.post(:poison)
102
+ sleep(0.1)
103
+ ivar.reason.should be_a StandardError
104
+
105
+ ivar = @ref.post(:bullet)
106
+ sleep(0.1)
107
+ ivar.reason.should be_nil
108
+ end
109
+
110
+ it 'defaults to false' do
111
+ @ref = create_actor_test_class.spawn(abort_on_exception: false)
112
+
113
+ ivar = @ref.post(:poison)
114
+ sleep(0.1)
115
+ ivar.reason.should be_a StandardError
116
+
117
+ ivar = @ref.post(:bullet)
118
+ sleep(0.1)
119
+ ivar.reason.should be_nil
120
+ end
121
+ end
122
+
123
+ context '#shutdown' do
124
+
125
+ it 'calls #on_shutdown when shutdown' do
126
+ actor = subject.instance_variable_get(:@actor)
127
+ actor.should_receive(:on_shutdown).once.with(no_args)
128
+ subject << :foo
129
+ sleep(0.1)
130
+
131
+ subject.shutdown
132
+ end
133
+ end
134
+ end
135
+ end