concurrent-ruby 0.6.1 → 0.7.0.rc0

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/concurrent.rb +3 -4
  4. data/lib/concurrent/atomic.rb +46 -0
  5. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  6. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  7. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  8. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  9. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  10. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  11. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  12. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  13. data/lib/concurrent/atomics.rb +1 -1
  14. data/lib/concurrent/configuration.rb +1 -1
  15. data/lib/concurrent/supervisor.rb +1 -1
  16. data/lib/concurrent/timer_task.rb +0 -36
  17. data/lib/concurrent/version.rb +1 -1
  18. data/lib/concurrent_ruby_ext.so +0 -0
  19. data/lib/extension_helper.rb +9 -0
  20. metadata +16 -148
  21. data/lib/concurrent/actor/actor.rb +0 -270
  22. data/lib/concurrent/actor/postable.rb +0 -102
  23. data/lib/concurrent/actors.rb +0 -2
  24. data/lib/concurrent/atomic/atomic.rb +0 -48
  25. data/lib/concurrent/runnable.rb +0 -90
  26. data/lib/concurrent/stoppable.rb +0 -20
  27. data/spec/concurrent/actor/actor_spec.rb +0 -376
  28. data/spec/concurrent/actor/postable_shared.rb +0 -218
  29. data/spec/concurrent/actress_spec.rb +0 -211
  30. data/spec/concurrent/agent_spec.rb +0 -500
  31. data/spec/concurrent/async_spec.rb +0 -352
  32. data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
  33. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
  34. data/spec/concurrent/atomic/atomic_spec.rb +0 -133
  35. data/spec/concurrent/atomic/condition_spec.rb +0 -171
  36. data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
  37. data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
  38. data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
  39. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
  40. data/spec/concurrent/atomic/event_spec.rb +0 -200
  41. data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
  42. data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
  43. data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
  44. data/spec/concurrent/channel/channel_spec.rb +0 -39
  45. data/spec/concurrent/channel/probe_spec.rb +0 -77
  46. data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
  47. data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
  48. data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
  49. data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
  50. data/spec/concurrent/configuration_spec.rb +0 -69
  51. data/spec/concurrent/dataflow_spec.rb +0 -242
  52. data/spec/concurrent/delay_spec.rb +0 -91
  53. data/spec/concurrent/dereferenceable_shared.rb +0 -146
  54. data/spec/concurrent/exchanger_spec.rb +0 -66
  55. data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
  56. data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
  57. data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
  58. data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
  59. data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
  60. data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
  61. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
  62. data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
  63. data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
  64. data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
  65. data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
  66. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
  67. data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
  68. data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
  69. data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
  70. data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
  71. data/spec/concurrent/executor/thread_pool_shared.rb +0 -269
  72. data/spec/concurrent/executor/timer_set_spec.rb +0 -183
  73. data/spec/concurrent/future_spec.rb +0 -329
  74. data/spec/concurrent/ivar_spec.rb +0 -215
  75. data/spec/concurrent/mvar_spec.rb +0 -380
  76. data/spec/concurrent/obligation_shared.rb +0 -102
  77. data/spec/concurrent/obligation_spec.rb +0 -282
  78. data/spec/concurrent/observable_shared.rb +0 -177
  79. data/spec/concurrent/observable_spec.rb +0 -56
  80. data/spec/concurrent/options_parser_spec.rb +0 -71
  81. data/spec/concurrent/promise_spec.rb +0 -367
  82. data/spec/concurrent/runnable_shared.rb +0 -68
  83. data/spec/concurrent/runnable_spec.rb +0 -235
  84. data/spec/concurrent/scheduled_task_spec.rb +0 -340
  85. data/spec/concurrent/stoppable_shared.rb +0 -37
  86. data/spec/concurrent/supervisor_spec.rb +0 -1149
  87. data/spec/concurrent/timer_task_spec.rb +0 -256
  88. data/spec/concurrent/tvar_spec.rb +0 -137
  89. data/spec/concurrent/utility/processor_count_spec.rb +0 -20
  90. data/spec/concurrent/utility/timeout_spec.rb +0 -50
  91. data/spec/concurrent/utility/timer_spec.rb +0 -52
  92. data/spec/spec_helper.rb +0 -41
  93. data/spec/support/example_group_extensions.rb +0 -52
  94. data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
@@ -1,103 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe SafeTaskExecutor do
6
-
7
- describe '#execute' do
8
-
9
- context 'happy execution' do
10
-
11
- let(:task) { Proc.new { 42 } }
12
- subject { SafeTaskExecutor.new(task) }
13
-
14
- it 'should return success' do
15
- success, value, reason = subject.execute
16
- success.should be_true
17
- end
18
-
19
- it 'should return task value' do
20
- success, value, reason = subject.execute
21
- value.should eq 42
22
- end
23
-
24
- it 'should return a nil reason' do
25
- success, value, reason = subject.execute
26
- reason.should be_nil
27
- end
28
-
29
- it 'passes all arguments to #execute to the task' do
30
- expected = nil
31
- task = proc {|*args| expected = args }
32
- SafeTaskExecutor.new(task).execute(1, 2, 3)
33
- expected.should eq [1, 2, 3]
34
- end
35
-
36
- it 'protectes #execute with a mutex' do
37
- mutex = double(:mutex)
38
- Mutex.should_receive(:new).with(no_args).and_return(mutex)
39
- mutex.should_receive(:synchronize).with(no_args)
40
- subject.execute
41
- end
42
- end
43
-
44
- context 'failing execution' do
45
-
46
- let(:task) { Proc.new { raise StandardError.new('an error') } }
47
- subject { SafeTaskExecutor.new(task) }
48
-
49
- it 'should return false success' do
50
- success, value, reason = subject.execute
51
- success.should be_false
52
- end
53
-
54
- it 'should return a nil value' do
55
- success, value, reason = subject.execute
56
- value.should be_nil
57
- end
58
-
59
- it 'should return the reason' do
60
- success, value, reason = subject.execute
61
- reason.should be_a(StandardError)
62
- reason.message.should eq 'an error'
63
- end
64
-
65
- it 'rescues Exception when :rescue_exception is true' do
66
- task = proc { raise Exception }
67
- subject = SafeTaskExecutor.new(task, rescue_exception: true)
68
- expect {
69
- subject.execute
70
- }.to_not raise_error
71
- end
72
-
73
- it 'rescues StandardError when :rescue_exception is false' do
74
- task = proc { raise StandardError }
75
- subject = SafeTaskExecutor.new(task, rescue_exception: false)
76
- expect {
77
- subject.execute
78
- }.to_not raise_error
79
-
80
- task = proc { raise Exception }
81
- subject = SafeTaskExecutor.new(task, rescue_exception: false)
82
- expect {
83
- subject.execute
84
- }.to raise_error(Exception)
85
- end
86
-
87
- it 'rescues StandardError by default' do
88
- task = proc { raise StandardError }
89
- subject = SafeTaskExecutor.new(task)
90
- expect {
91
- subject.execute
92
- }.to_not raise_error
93
-
94
- task = proc { raise Exception }
95
- subject = SafeTaskExecutor.new(task)
96
- expect {
97
- subject.execute
98
- }.to raise_error(Exception)
99
- end
100
- end
101
- end
102
- end
103
- end
@@ -1,52 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe SingleThreadExecutor do
6
- if jruby?
7
- it 'inherits from JavaSingleThreadExecutor' do
8
- SingleThreadExecutor.ancestors.should include(JavaSingleThreadExecutor)
9
- end
10
- else
11
- it 'inherits from RubySingleThreadExecutor' do
12
- SingleThreadExecutor.ancestors.should include(RubySingleThreadExecutor)
13
- end
14
- end
15
- end
16
-
17
- describe ThreadPoolExecutor do
18
- if jruby?
19
- it 'inherits from JavaThreadPoolExecutor' do
20
- ThreadPoolExecutor.ancestors.should include(JavaThreadPoolExecutor)
21
- end
22
- else
23
- it 'inherits from RubyThreadPoolExecutor' do
24
- ThreadPoolExecutor.ancestors.should include(RubyThreadPoolExecutor)
25
- end
26
- end
27
- end
28
-
29
- describe CachedThreadPool do
30
- if jruby?
31
- it 'inherits from JavaCachedThreadPool' do
32
- CachedThreadPool.ancestors.should include(JavaCachedThreadPool)
33
- end
34
- else
35
- it 'inherits from RubyCachedThreadPool' do
36
- CachedThreadPool.ancestors.should include(RubyCachedThreadPool)
37
- end
38
- end
39
- end
40
-
41
- describe FixedThreadPool do
42
- if jruby?
43
- it 'inherits from JavaFixedThreadPool' do
44
- FixedThreadPool.ancestors.should include(JavaFixedThreadPool)
45
- end
46
- else
47
- it 'inherits from RubyFixedThreadPool' do
48
- FixedThreadPool.ancestors.should include(RubyFixedThreadPool)
49
- end
50
- end
51
- end
52
- end
@@ -1,155 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'thread_pool_shared'
3
-
4
- share_examples_for :thread_pool_executor do
5
-
6
- after(:each) do
7
- subject.kill
8
- sleep(0.1)
9
- end
10
-
11
- it_should_behave_like :thread_pool
12
-
13
- context '#initialize' do
14
-
15
- it 'defaults :min_length to DEFAULT_MIN_POOL_SIZE' do
16
- subject = described_class.new
17
- subject.min_length.should eq described_class::DEFAULT_MIN_POOL_SIZE
18
- end
19
-
20
- it 'defaults :max_length to DEFAULT_MAX_POOL_SIZE' do
21
- subject = described_class.new
22
- subject.max_length.should eq described_class::DEFAULT_MAX_POOL_SIZE
23
- end
24
-
25
- it 'defaults :idletime to DEFAULT_THREAD_IDLETIMEOUT' do
26
- subject = described_class.new
27
- subject.idletime.should eq described_class::DEFAULT_THREAD_IDLETIMEOUT
28
- end
29
-
30
- it 'defaults :max_queue to DEFAULT_MAX_QUEUE_SIZE' do
31
- subject = described_class.new
32
- subject.max_queue.should eq described_class::DEFAULT_MAX_QUEUE_SIZE
33
- end
34
-
35
- it 'accepts all valid overflow policies' do
36
- Concurrent::RubyThreadPoolExecutor::OVERFLOW_POLICIES.each do |policy|
37
- subject = described_class.new(overflow_policy: policy)
38
- subject.overflow_policy.should eq policy
39
- end
40
- end
41
-
42
- it 'defaults :overflow_policy to :abort' do
43
- subject = described_class.new
44
- subject.overflow_policy.should eq :abort
45
- end
46
-
47
- it 'raises an exception if :min_threads is less than zero' do
48
- expect {
49
- described_class.new(min_threads: -1)
50
- }.to raise_error(ArgumentError)
51
- end
52
-
53
- it 'raises an exception if :max_threads is not greater than zero' do
54
- expect {
55
- described_class.new(max_threads: 0)
56
- }.to raise_error(ArgumentError)
57
- end
58
-
59
- it 'raises an exception if given an invalid :overflow_policy' do
60
- expect {
61
- described_class.new(overflow_policy: :bogus)
62
- }.to raise_error(ArgumentError)
63
- end
64
- end
65
-
66
- context '#max_queue' do
67
-
68
- let!(:expected_max){ 100 }
69
- subject{ described_class.new(max_queue: expected_max) }
70
-
71
- it 'returns the set value on creation' do
72
- subject.max_queue.should eq expected_max
73
- end
74
-
75
- it 'returns the set value when running' do
76
- 5.times{ subject.post{ sleep(0.1) } }
77
- sleep(0.1)
78
- subject.max_queue.should eq expected_max
79
- end
80
-
81
- it 'returns the set value after stopping' do
82
- 5.times{ subject.post{ sleep(0.1) } }
83
- sleep(0.1)
84
- subject.shutdown
85
- subject.wait_for_termination(1)
86
- subject.max_queue.should eq expected_max
87
- end
88
- end
89
-
90
- context '#queue_length' do
91
-
92
- let!(:expected_max){ 10 }
93
- subject do
94
- described_class.new(
95
- min_threads: 2,
96
- max_threads: 5,
97
- max_queue: expected_max,
98
- overflow_policy: :discard
99
- )
100
- end
101
-
102
- it 'returns zero on creation' do
103
- subject.queue_length.should eq 0
104
- end
105
-
106
- it 'returns zero when there are no enqueued tasks' do
107
- 5.times{ subject.post{ nil } }
108
- sleep(0.1)
109
- subject.queue_length.should eq 0
110
- end
111
-
112
- it 'returns the size of the queue when tasks are enqueued' do
113
- 100.times{ subject.post{ sleep(0.5) } }
114
- sleep(0.1)
115
- subject.queue_length.should > 0
116
- end
117
-
118
- it 'returns zero when stopped' do
119
- 100.times{ subject.post{ sleep(0.5) } }
120
- sleep(0.1)
121
- subject.shutdown
122
- subject.wait_for_termination(1)
123
- subject.queue_length.should eq 0
124
- end
125
-
126
- it 'can never be greater than :max_queue' do
127
- 100.times{ subject.post{ sleep(0.5) } }
128
- sleep(0.1)
129
- subject.queue_length.should <= expected_max
130
- end
131
- end
132
-
133
- context '#remaining_capacity' do
134
-
135
- let!(:expected_max){ 100 }
136
- subject{ described_class.new(max_queue: expected_max) }
137
-
138
- it 'returns -1 when :max_queue is set to zero' do
139
- executor = described_class.new(max_queue: 0)
140
- executor.remaining_capacity.should eq -1
141
- end
142
-
143
- it 'returns :max_length on creation' do
144
- subject.remaining_capacity.should eq expected_max
145
- end
146
-
147
- it 'returns :max_length when stopped' do
148
- 100.times{ subject.post{ nil } }
149
- sleep(0.1)
150
- subject.shutdown
151
- subject.wait_for_termination(1)
152
- subject.remaining_capacity.should eq expected_max
153
- end
154
- end
155
- end
@@ -1,269 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'global_thread_pool_shared'
3
-
4
- share_examples_for :executor_service do
5
-
6
- after(:each) do
7
- subject.kill
8
- sleep(0.1)
9
- end
10
-
11
- it_should_behave_like :global_thread_pool
12
-
13
- context '#post' do
14
-
15
- it 'rejects the block while shutting down' do
16
- latch = Concurrent::CountDownLatch.new(1)
17
- subject.post{ sleep(1) }
18
- subject.shutdown
19
- subject.post{ latch.count_down }
20
- latch.wait(0.1).should be_false
21
- end
22
-
23
- it 'returns false while shutting down' do
24
- subject.post{ sleep(1) }
25
- subject.shutdown
26
- subject.post{ nil }.should be_false
27
- end
28
-
29
- it 'rejects the block once shutdown' do
30
- subject.shutdown
31
- latch = Concurrent::CountDownLatch.new(1)
32
- subject.post{ sleep(1) }
33
- subject.post{ latch.count_down }
34
- latch.wait(0.1).should be_false
35
- end
36
-
37
- it 'returns false once shutdown' do
38
- subject.post{ nil }
39
- subject.shutdown
40
- sleep(0.1)
41
- subject.post{ nil }.should be_false
42
- end
43
- end
44
-
45
- context '#running?' do
46
-
47
- it 'returns true when the thread pool is running' do
48
- subject.should be_running
49
- end
50
-
51
- it 'returns false when the thread pool is shutting down' do
52
- subject.post{ sleep(1) }
53
- subject.shutdown
54
- subject.wait_for_termination(1)
55
- subject.should_not be_running
56
- end
57
-
58
- it 'returns false when the thread pool is shutdown' do
59
- subject.shutdown
60
- subject.wait_for_termination(1)
61
- subject.should_not be_running
62
- end
63
-
64
- it 'returns false when the thread pool is killed' do
65
- subject.kill
66
- subject.wait_for_termination(1)
67
- subject.should_not be_running
68
- end
69
- end
70
-
71
- context '#shutdown' do
72
-
73
- it 'stops accepting new tasks' do
74
- subject.post{ sleep(1) }
75
- sleep(0.1)
76
- subject.shutdown
77
- @expected = false
78
- subject.post{ @expected = true }.should be_false
79
- sleep(1)
80
- @expected.should be_false
81
- end
82
-
83
- it 'allows in-progress tasks to complete' do
84
- @expected = false
85
- subject.post{ @expected = true }
86
- sleep(0.1)
87
- subject.shutdown
88
- sleep(1)
89
- @expected.should be_true
90
- end
91
-
92
- it 'allows pending tasks to complete' do
93
- @expected = false
94
- subject.post{ sleep(0.2) }
95
- subject.post{ sleep(0.2); @expected = true }
96
- sleep(0.1)
97
- subject.shutdown
98
- sleep(1)
99
- @expected.should be_true
100
- end
101
- end
102
-
103
- context '#shutdown followed by #wait_for_termination' do
104
- it "allows in-progress tasks to complete" do
105
- @expected = false
106
- subject.post{ sleep 0.1; @expected = true }
107
- subject.shutdown
108
- subject.wait_for_termination(1)
109
- @expected.should be_true
110
- end
111
-
112
- it 'allows pending tasks to complete' do
113
- @expected = false
114
- subject.post{ sleep(0.1) }
115
- subject.post{ sleep(0.1); @expected = true }
116
- subject.shutdown
117
- subject.wait_for_termination(1)
118
- @expected.should be_true
119
- end
120
-
121
- it "stops accepting/running new tasks" do
122
- @expected = :start
123
- subject.post{ sleep(0.1) }
124
- subject.post{ sleep(0.1); @expected = :should_be_run }
125
- subject.shutdown
126
- subject.post{ @expected = :should_not_be_run }
127
- subject.wait_for_termination(1)
128
- @expected.should == :should_be_run
129
- end
130
- end
131
-
132
-
133
- context '#kill' do
134
-
135
- it 'stops accepting new tasks' do
136
- subject.post{ sleep(1) }
137
- sleep(0.1)
138
- subject.kill
139
- @expected = false
140
- subject.post{ @expected = true }.should be_false
141
- sleep(1)
142
- @expected.should be_false
143
- end
144
-
145
- it 'rejects all pending tasks' do
146
- subject.post{ sleep(1) }
147
- sleep(0.1)
148
- subject.kill
149
- sleep(0.1)
150
- subject.post{ nil }.should be_false
151
- end
152
- end
153
-
154
- context '#wait_for_termination' do
155
-
156
- it 'immediately returns true when no operations are pending' do
157
- subject.shutdown
158
- subject.wait_for_termination(0).should be_true
159
- end
160
-
161
- it 'returns true after shutdown has complete' do
162
- 10.times { subject << proc{ nil } }
163
- sleep(0.1)
164
- subject.shutdown
165
- subject.wait_for_termination(1).should be_true
166
- end
167
-
168
- it 'returns true when shutdown sucessfully completes before timeout' do
169
- subject.post{ sleep(0.5) }
170
- sleep(0.1)
171
- subject.shutdown
172
- subject.wait_for_termination(1).should be_true
173
- end
174
-
175
- it 'returns false when shutdown fails to complete before timeout' do
176
- 100.times{ subject.post{ sleep(1) } }
177
- sleep(0.1)
178
- subject.shutdown
179
- subject.wait_for_termination(0).should be_false
180
- end
181
- end
182
- end
183
-
184
- share_examples_for :thread_pool do
185
-
186
- after(:each) do
187
- subject.kill
188
- sleep(0.1)
189
- end
190
-
191
- it_should_behave_like :executor_service
192
-
193
- context '#length' do
194
-
195
- it 'returns zero on creation' do
196
- subject.length.should eq 0
197
- end
198
-
199
- it 'returns zero once shut down' do
200
- 5.times{ subject.post{ sleep(0.1) } }
201
- sleep(0.1)
202
- subject.shutdown
203
- subject.wait_for_termination(1)
204
- subject.length.should eq 0
205
- end
206
-
207
- it 'aliased as #current_length' do
208
- 5.times{ subject.post{ sleep(0.1) } }
209
- sleep(0.1)
210
- subject.current_length.should eq subject.length
211
- end
212
- end
213
-
214
- context '#scheduled_task_count' do
215
-
216
- it 'returns zero on creation' do
217
- subject.scheduled_task_count.should eq 0
218
- end
219
-
220
- it 'returns the approximate number of tasks that have been post thus far' do
221
- 10.times{ subject.post{ nil } }
222
- sleep(0.1)
223
- subject.scheduled_task_count.should > 0
224
- end
225
-
226
- it 'returns the approximate number of tasks that were post' do
227
- 10.times{ subject.post{ nil } }
228
- sleep(0.1)
229
- subject.shutdown
230
- subject.wait_for_termination(1)
231
- subject.scheduled_task_count.should > 0
232
- end
233
- end
234
-
235
- context '#completed_task_count' do
236
-
237
- it 'returns zero on creation' do
238
- subject.completed_task_count.should eq 0
239
- end
240
-
241
- it 'returns the approximate number of tasks that have been completed thus far' do
242
- 5.times{ subject.post{ raise StandardError } }
243
- 5.times{ subject.post{ nil } }
244
- sleep(0.1)
245
- subject.completed_task_count.should > 0
246
- end
247
-
248
- it 'returns the approximate number of tasks that were completed' do
249
- 5.times{ subject.post{ raise StandardError } }
250
- 5.times{ subject.post{ nil } }
251
- sleep(0.1)
252
- subject.shutdown
253
- subject.wait_for_termination(1)
254
- subject.completed_task_count.should > 0
255
- end
256
- end
257
-
258
- context '#shutdown' do
259
-
260
- it 'allows threads to exit normally' do
261
- 10.times{ subject << proc{ nil } }
262
- subject.length.should > 0
263
- sleep(0.1)
264
- subject.shutdown
265
- sleep(1)
266
- subject.length.should == 0
267
- end
268
- end
269
- end