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

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 (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