concurrent-ruby 0.6.0 → 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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +55 -51
  3. data/lib/concurrent/actress/ad_hoc.rb +6 -0
  4. data/lib/concurrent/actress/context.rb +10 -8
  5. data/lib/concurrent/actress/core.rb +44 -20
  6. data/lib/concurrent/actress/core_delegations.rb +5 -0
  7. data/lib/concurrent/actress/envelope.rb +21 -5
  8. data/lib/concurrent/actress/reference.rb +5 -5
  9. data/lib/concurrent/actress.rb +152 -6
  10. data/lib/concurrent/agent.rb +9 -9
  11. data/lib/concurrent/atomic.rb +46 -0
  12. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
  13. data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
  14. data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
  15. data/lib/concurrent/atomic_reference/jruby.rb +8 -0
  16. data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
  17. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
  18. data/lib/concurrent/atomic_reference/rbx.rb +16 -0
  19. data/lib/concurrent/atomic_reference/ruby.rb +16 -0
  20. data/lib/concurrent/atomics.rb +1 -1
  21. data/lib/concurrent/configuration.rb +7 -2
  22. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +0 -1
  23. data/lib/concurrent/executor/{one_by_one.rb → serialized_execution.rb} +21 -8
  24. data/lib/concurrent/executor/timer_set.rb +6 -1
  25. data/lib/concurrent/executors.rb +1 -1
  26. data/lib/concurrent/logging.rb +1 -1
  27. data/lib/concurrent/observable.rb +1 -1
  28. data/lib/concurrent/supervisor.rb +1 -1
  29. data/lib/concurrent/timer_task.rb +0 -36
  30. data/lib/concurrent/version.rb +1 -1
  31. data/lib/concurrent.rb +3 -4
  32. data/lib/concurrent_ruby_ext.so +0 -0
  33. data/lib/extension_helper.rb +9 -0
  34. metadata +19 -152
  35. data/lib/concurrent/actor/actor.rb +0 -270
  36. data/lib/concurrent/actor/postable.rb +0 -102
  37. data/lib/concurrent/actors.rb +0 -2
  38. data/lib/concurrent/actress/doc.md +0 -53
  39. data/lib/concurrent/atomic/atomic.rb +0 -48
  40. data/lib/concurrent/runnable.rb +0 -90
  41. data/lib/concurrent/stoppable.rb +0 -20
  42. data/spec/concurrent/actor/actor_spec.rb +0 -376
  43. data/spec/concurrent/actor/postable_shared.rb +0 -218
  44. data/spec/concurrent/actress_spec.rb +0 -191
  45. data/spec/concurrent/agent_spec.rb +0 -500
  46. data/spec/concurrent/async_spec.rb +0 -352
  47. data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
  48. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
  49. data/spec/concurrent/atomic/atomic_spec.rb +0 -133
  50. data/spec/concurrent/atomic/condition_spec.rb +0 -171
  51. data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
  52. data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
  53. data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
  54. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
  55. data/spec/concurrent/atomic/event_spec.rb +0 -200
  56. data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
  57. data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
  58. data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
  59. data/spec/concurrent/channel/channel_spec.rb +0 -39
  60. data/spec/concurrent/channel/probe_spec.rb +0 -77
  61. data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
  62. data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
  63. data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
  64. data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
  65. data/spec/concurrent/configuration_spec.rb +0 -71
  66. data/spec/concurrent/dataflow_spec.rb +0 -242
  67. data/spec/concurrent/delay_spec.rb +0 -91
  68. data/spec/concurrent/dereferenceable_shared.rb +0 -146
  69. data/spec/concurrent/exchanger_spec.rb +0 -66
  70. data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
  71. data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
  72. data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
  73. data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
  74. data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
  75. data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
  76. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
  77. data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
  78. data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
  79. data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
  80. data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
  81. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
  82. data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
  83. data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
  84. data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
  85. data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
  86. data/spec/concurrent/executor/thread_pool_shared.rb +0 -239
  87. data/spec/concurrent/executor/timer_set_spec.rb +0 -183
  88. data/spec/concurrent/future_spec.rb +0 -329
  89. data/spec/concurrent/ivar_spec.rb +0 -215
  90. data/spec/concurrent/mvar_spec.rb +0 -380
  91. data/spec/concurrent/obligation_shared.rb +0 -102
  92. data/spec/concurrent/obligation_spec.rb +0 -282
  93. data/spec/concurrent/observable_shared.rb +0 -177
  94. data/spec/concurrent/observable_spec.rb +0 -56
  95. data/spec/concurrent/options_parser_spec.rb +0 -71
  96. data/spec/concurrent/promise_spec.rb +0 -367
  97. data/spec/concurrent/runnable_shared.rb +0 -68
  98. data/spec/concurrent/runnable_spec.rb +0 -235
  99. data/spec/concurrent/scheduled_task_spec.rb +0 -342
  100. data/spec/concurrent/stoppable_shared.rb +0 -37
  101. data/spec/concurrent/supervisor_spec.rb +0 -1148
  102. data/spec/concurrent/timer_task_spec.rb +0 -258
  103. data/spec/concurrent/tvar_spec.rb +0 -137
  104. data/spec/concurrent/utility/processor_count_spec.rb +0 -20
  105. data/spec/concurrent/utility/timeout_spec.rb +0 -50
  106. data/spec/concurrent/utility/timer_spec.rb +0 -52
  107. data/spec/spec_helper.rb +0 -31
  108. data/spec/support/example_group_extensions.rb +0 -48
  109. data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
  110. /data/{LICENSE → LICENSE.txt} +0 -0
@@ -1,171 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'thread_pool_executor_shared'
3
-
4
- module Concurrent
5
-
6
- describe RubyThreadPoolExecutor do
7
-
8
- after(:each) do
9
- subject.kill
10
- sleep(0.1)
11
- end
12
-
13
- subject do
14
- RubyThreadPoolExecutor.new(
15
- min_threads: 2,
16
- max_threads: 5,
17
- idletime: 60,
18
- max_queue: 10,
19
- overflow_policy: :discard
20
- )
21
- end
22
-
23
- it_should_behave_like :thread_pool_executor
24
-
25
- context '#remaining_capacity' do
26
-
27
- let!(:expected_max){ 100 }
28
-
29
- subject do
30
- RubyThreadPoolExecutor.new(
31
- min_threads: 10,
32
- max_threads: 20,
33
- idletime: 60,
34
- max_queue: expected_max,
35
- overflow_policy: :discard
36
- )
37
- end
38
-
39
- it 'returns :max_length when no tasks are enqueued' do
40
- 5.times{ subject.post{ nil } }
41
- sleep(0.1)
42
- subject.remaining_capacity.should eq expected_max
43
- end
44
-
45
- it 'returns the remaining capacity when tasks are enqueued' do
46
- 100.times{ subject.post{ sleep(0.5) } }
47
- sleep(0.1)
48
- subject.remaining_capacity.should < expected_max
49
- end
50
- end
51
-
52
- context '#overload_policy' do
53
-
54
- let!(:min_threads){ 1 }
55
- let!(:max_threads){ 1 }
56
- let!(:idletime){ 60 }
57
- let!(:max_queue){ 1 }
58
-
59
- context ':abort' do
60
-
61
- subject do
62
- described_class.new(
63
- min_threads: min_threads,
64
- max_threads: max_threads,
65
- idletime: idletime,
66
- max_queue: max_queue,
67
- overflow_policy: :abort
68
- )
69
- end
70
-
71
- specify '#post raises an error when the queue is at capacity' do
72
- expect {
73
- 100.times{ subject.post{ sleep(1) } }
74
- }.to raise_error(Concurrent::RejectedExecutionError)
75
- end
76
-
77
- specify '#<< raises an error when the queue is at capacity' do
78
- expect {
79
- 100.times{ subject << proc { sleep(1) } }
80
- }.to raise_error(Concurrent::RejectedExecutionError)
81
- end
82
-
83
- specify 'a #post task is never executed when the queue is at capacity' do
84
- executed = Concurrent::AtomicFixnum.new(0)
85
- 10.times do
86
- begin
87
- subject.post{ executed.increment; sleep(0.1) }
88
- rescue
89
- end
90
- end
91
- sleep(0.2)
92
- executed.value.should < 10
93
- end
94
-
95
- specify 'a #<< task is never executed when the queue is at capacity' do
96
- executed = Concurrent::AtomicFixnum.new(0)
97
- 10.times do
98
- begin
99
- subject << proc { executed.increment; sleep(0.1) }
100
- rescue
101
- end
102
- end
103
- sleep(0.2)
104
- executed.value.should < 10
105
- end
106
- end
107
-
108
- context ':discard' do
109
-
110
- subject do
111
- described_class.new(
112
- min_threads: min_threads,
113
- max_threads: max_threads,
114
- idletime: idletime,
115
- max_queue: max_queue,
116
- overflow_policy: :discard
117
- )
118
- end
119
-
120
- specify 'a #post task is never executed when the queue is at capacity' do
121
- executed = Concurrent::AtomicFixnum.new(0)
122
- 1000.times do
123
- subject.post{ executed.increment }
124
- end
125
- sleep(0.1)
126
- executed.value.should < 1000
127
- end
128
-
129
- specify 'a #<< task is never executed when the queue is at capacity' do
130
- executed = Concurrent::AtomicFixnum.new(0)
131
- 1000.times do
132
- subject << proc { executed.increment }
133
- end
134
- sleep(0.1)
135
- executed.value.should < 1000
136
- end
137
- end
138
-
139
- context ':caller_runs' do
140
-
141
- subject do
142
- described_class.new(
143
- min_threads: 1,
144
- max_threads: 1,
145
- idletime: idletime,
146
- max_queue: 1,
147
- overflow_policy: :caller_runs
148
- )
149
- end
150
-
151
- specify '#post does not create any new threads when the queue is at capacity' do
152
- initial = Thread.list.length
153
- 5.times{ subject.post{ sleep(0.1) } }
154
- Thread.list.length.should < initial + 5
155
- end
156
-
157
- specify '#<< executes the task on the current thread when the queue is at capacity' do
158
- subject.should_receive(:handle_overflow).with(any_args).at_least(:once)
159
- 5.times{ subject << proc { sleep(0.1) } }
160
- end
161
-
162
- specify '#post executes the task on the current thread when the queue is at capacity' do
163
- latch = Concurrent::CountDownLatch.new(5)
164
- subject.post{ sleep(1) }
165
- 5.times{|i| subject.post{ latch.count_down } }
166
- latch.wait(0.1)
167
- end
168
- end
169
- end
170
- end
171
- end
@@ -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,239 +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 '#kill' do
104
-
105
- it 'stops accepting new tasks' do
106
- subject.post{ sleep(1) }
107
- sleep(0.1)
108
- subject.kill
109
- @expected = false
110
- subject.post{ @expected = true }.should be_false
111
- sleep(1)
112
- @expected.should be_false
113
- end
114
-
115
- it 'rejects all pending tasks' do
116
- subject.post{ sleep(1) }
117
- sleep(0.1)
118
- subject.kill
119
- sleep(0.1)
120
- subject.post{ nil }.should be_false
121
- end
122
- end
123
-
124
- context '#wait_for_termination' do
125
-
126
- it 'immediately returns true when no operations are pending' do
127
- subject.shutdown
128
- subject.wait_for_termination(0).should be_true
129
- end
130
-
131
- it 'returns true after shutdown has complete' do
132
- 10.times { subject << proc{ nil } }
133
- sleep(0.1)
134
- subject.shutdown
135
- subject.wait_for_termination(1).should be_true
136
- end
137
-
138
- it 'returns true when shutdown sucessfully completes before timeout' do
139
- subject.post{ sleep(0.5) }
140
- sleep(0.1)
141
- subject.shutdown
142
- subject.wait_for_termination(1).should be_true
143
- end
144
-
145
- it 'returns false when shutdown fails to complete before timeout' do
146
- 100.times{ subject.post{ sleep(1) } }
147
- sleep(0.1)
148
- subject.shutdown
149
- subject.wait_for_termination(0).should be_false
150
- end
151
- end
152
- end
153
-
154
- share_examples_for :thread_pool do
155
-
156
- after(:each) do
157
- subject.kill
158
- sleep(0.1)
159
- end
160
-
161
- it_should_behave_like :executor_service
162
-
163
- context '#length' do
164
-
165
- it 'returns zero on creation' do
166
- subject.length.should eq 0
167
- end
168
-
169
- it 'returns zero once shut down' do
170
- 5.times{ subject.post{ sleep(0.1) } }
171
- sleep(0.1)
172
- subject.shutdown
173
- subject.wait_for_termination(1)
174
- subject.length.should eq 0
175
- end
176
-
177
- it 'aliased as #current_length' do
178
- 5.times{ subject.post{ sleep(0.1) } }
179
- sleep(0.1)
180
- subject.current_length.should eq subject.length
181
- end
182
- end
183
-
184
- context '#scheduled_task_count' do
185
-
186
- it 'returns zero on creation' do
187
- subject.scheduled_task_count.should eq 0
188
- end
189
-
190
- it 'returns the approximate number of tasks that have been post thus far' do
191
- 10.times{ subject.post{ nil } }
192
- sleep(0.1)
193
- subject.scheduled_task_count.should > 0
194
- end
195
-
196
- it 'returns the approximate number of tasks that were post' do
197
- 10.times{ subject.post{ nil } }
198
- sleep(0.1)
199
- subject.shutdown
200
- subject.wait_for_termination(1)
201
- subject.scheduled_task_count.should > 0
202
- end
203
- end
204
-
205
- context '#completed_task_count' do
206
-
207
- it 'returns zero on creation' do
208
- subject.completed_task_count.should eq 0
209
- end
210
-
211
- it 'returns the approximate number of tasks that have been completed thus far' do
212
- 5.times{ subject.post{ raise StandardError } }
213
- 5.times{ subject.post{ nil } }
214
- sleep(0.1)
215
- subject.completed_task_count.should > 0
216
- end
217
-
218
- it 'returns the approximate number of tasks that were completed' do
219
- 5.times{ subject.post{ raise StandardError } }
220
- 5.times{ subject.post{ nil } }
221
- sleep(0.1)
222
- subject.shutdown
223
- subject.wait_for_termination(1)
224
- subject.completed_task_count.should > 0
225
- end
226
- end
227
-
228
- context '#shutdown' do
229
-
230
- it 'allows threads to exit normally' do
231
- 10.times{ subject << proc{ nil } }
232
- subject.length.should > 0
233
- sleep(0.1)
234
- subject.shutdown
235
- sleep(1)
236
- subject.length.should == 0
237
- end
238
- end
239
- end