concurrent-ruby 0.6.1 → 0.7.0.rc0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/concurrent.rb +3 -4
- data/lib/concurrent/atomic.rb +46 -0
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
- data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
- data/lib/concurrent/atomic_reference/jruby.rb +8 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
- data/lib/concurrent/atomic_reference/rbx.rb +16 -0
- data/lib/concurrent/atomic_reference/ruby.rb +16 -0
- data/lib/concurrent/atomics.rb +1 -1
- data/lib/concurrent/configuration.rb +1 -1
- data/lib/concurrent/supervisor.rb +1 -1
- data/lib/concurrent/timer_task.rb +0 -36
- data/lib/concurrent/version.rb +1 -1
- data/lib/concurrent_ruby_ext.so +0 -0
- data/lib/extension_helper.rb +9 -0
- metadata +16 -148
- data/lib/concurrent/actor/actor.rb +0 -270
- data/lib/concurrent/actor/postable.rb +0 -102
- data/lib/concurrent/actors.rb +0 -2
- data/lib/concurrent/atomic/atomic.rb +0 -48
- data/lib/concurrent/runnable.rb +0 -90
- data/lib/concurrent/stoppable.rb +0 -20
- data/spec/concurrent/actor/actor_spec.rb +0 -376
- data/spec/concurrent/actor/postable_shared.rb +0 -218
- data/spec/concurrent/actress_spec.rb +0 -211
- data/spec/concurrent/agent_spec.rb +0 -500
- data/spec/concurrent/async_spec.rb +0 -352
- data/spec/concurrent/atomic/atomic_boolean_spec.rb +0 -172
- data/spec/concurrent/atomic/atomic_fixnum_spec.rb +0 -186
- data/spec/concurrent/atomic/atomic_spec.rb +0 -133
- data/spec/concurrent/atomic/condition_spec.rb +0 -171
- data/spec/concurrent/atomic/copy_on_notify_observer_set_spec.rb +0 -10
- data/spec/concurrent/atomic/copy_on_write_observer_set_spec.rb +0 -10
- data/spec/concurrent/atomic/count_down_latch_spec.rb +0 -151
- data/spec/concurrent/atomic/cyclic_barrier_spec.rb +0 -248
- data/spec/concurrent/atomic/event_spec.rb +0 -200
- data/spec/concurrent/atomic/observer_set_shared.rb +0 -242
- data/spec/concurrent/atomic/thread_local_var_spec.rb +0 -113
- data/spec/concurrent/channel/buffered_channel_spec.rb +0 -151
- data/spec/concurrent/channel/channel_spec.rb +0 -39
- data/spec/concurrent/channel/probe_spec.rb +0 -77
- data/spec/concurrent/channel/unbuffered_channel_spec.rb +0 -132
- data/spec/concurrent/collection/blocking_ring_buffer_spec.rb +0 -149
- data/spec/concurrent/collection/priority_queue_spec.rb +0 -317
- data/spec/concurrent/collection/ring_buffer_spec.rb +0 -126
- data/spec/concurrent/configuration_spec.rb +0 -69
- data/spec/concurrent/dataflow_spec.rb +0 -242
- data/spec/concurrent/delay_spec.rb +0 -91
- data/spec/concurrent/dereferenceable_shared.rb +0 -146
- data/spec/concurrent/exchanger_spec.rb +0 -66
- data/spec/concurrent/executor/cached_thread_pool_shared.rb +0 -115
- data/spec/concurrent/executor/fixed_thread_pool_shared.rb +0 -136
- data/spec/concurrent/executor/global_thread_pool_shared.rb +0 -35
- data/spec/concurrent/executor/immediate_executor_spec.rb +0 -12
- data/spec/concurrent/executor/java_cached_thread_pool_spec.rb +0 -44
- data/spec/concurrent/executor/java_fixed_thread_pool_spec.rb +0 -64
- data/spec/concurrent/executor/java_single_thread_executor_spec.rb +0 -21
- data/spec/concurrent/executor/java_thread_pool_executor_spec.rb +0 -71
- data/spec/concurrent/executor/per_thread_executor_spec.rb +0 -57
- data/spec/concurrent/executor/ruby_cached_thread_pool_spec.rb +0 -69
- data/spec/concurrent/executor/ruby_fixed_thread_pool_spec.rb +0 -39
- data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +0 -18
- data/spec/concurrent/executor/ruby_thread_pool_executor_spec.rb +0 -171
- data/spec/concurrent/executor/safe_task_executor_spec.rb +0 -103
- data/spec/concurrent/executor/thread_pool_class_cast_spec.rb +0 -52
- data/spec/concurrent/executor/thread_pool_executor_shared.rb +0 -155
- data/spec/concurrent/executor/thread_pool_shared.rb +0 -269
- data/spec/concurrent/executor/timer_set_spec.rb +0 -183
- data/spec/concurrent/future_spec.rb +0 -329
- data/spec/concurrent/ivar_spec.rb +0 -215
- data/spec/concurrent/mvar_spec.rb +0 -380
- data/spec/concurrent/obligation_shared.rb +0 -102
- data/spec/concurrent/obligation_spec.rb +0 -282
- data/spec/concurrent/observable_shared.rb +0 -177
- data/spec/concurrent/observable_spec.rb +0 -56
- data/spec/concurrent/options_parser_spec.rb +0 -71
- data/spec/concurrent/promise_spec.rb +0 -367
- data/spec/concurrent/runnable_shared.rb +0 -68
- data/spec/concurrent/runnable_spec.rb +0 -235
- data/spec/concurrent/scheduled_task_spec.rb +0 -340
- data/spec/concurrent/stoppable_shared.rb +0 -37
- data/spec/concurrent/supervisor_spec.rb +0 -1149
- data/spec/concurrent/timer_task_spec.rb +0 -256
- data/spec/concurrent/tvar_spec.rb +0 -137
- data/spec/concurrent/utility/processor_count_spec.rb +0 -20
- data/spec/concurrent/utility/timeout_spec.rb +0 -50
- data/spec/concurrent/utility/timer_spec.rb +0 -52
- data/spec/spec_helper.rb +0 -41
- data/spec/support/example_group_extensions.rb +0 -52
- data/spec/support/less_than_or_equal_to_matcher.rb +0 -5
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for :global_thread_pool do
|
4
|
-
|
5
|
-
context '#post' do
|
6
|
-
|
7
|
-
it 'raises an exception if no block is given' do
|
8
|
-
lambda {
|
9
|
-
subject.post
|
10
|
-
}.should raise_error(ArgumentError)
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'returns true when the block is added to the queue' do
|
14
|
-
subject.post{ nil }.should be_true
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'calls the block with the given arguments' do
|
18
|
-
latch = Concurrent::CountDownLatch.new(1)
|
19
|
-
expected = nil
|
20
|
-
subject.post(1, 2, 3) do |a, b, c|
|
21
|
-
expected = [a, b, c]
|
22
|
-
latch.count_down
|
23
|
-
end
|
24
|
-
latch.wait(0.2)
|
25
|
-
expected.should eq [1, 2, 3]
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'aliases #<<' do
|
29
|
-
latch = Concurrent::CountDownLatch.new(1)
|
30
|
-
subject << proc { latch.count_down }
|
31
|
-
latch.wait(0.2)
|
32
|
-
latch.count.should eq 0
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
if Concurrent::TestHelpers.jruby?
|
4
|
-
|
5
|
-
require_relative 'cached_thread_pool_shared'
|
6
|
-
|
7
|
-
module Concurrent
|
8
|
-
|
9
|
-
describe JavaCachedThreadPool do
|
10
|
-
|
11
|
-
subject { described_class.new(overflow_policy: :discard) }
|
12
|
-
|
13
|
-
after(:each) do
|
14
|
-
subject.kill
|
15
|
-
sleep(0.1)
|
16
|
-
end
|
17
|
-
|
18
|
-
it_should_behave_like :cached_thread_pool
|
19
|
-
|
20
|
-
context '#initialize' do
|
21
|
-
|
22
|
-
it 'sets :overflow_policy correctly' do
|
23
|
-
clazz = java.util.concurrent.ThreadPoolExecutor::DiscardPolicy
|
24
|
-
policy = clazz.new
|
25
|
-
clazz.should_receive(:new).at_least(:once).with(any_args).and_return(policy)
|
26
|
-
|
27
|
-
subject = JavaCachedThreadPool.new(overflow_policy: :discard)
|
28
|
-
subject.overflow_policy.should eq :discard
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'defaults :overflow_policy to :abort' do
|
32
|
-
subject = JavaCachedThreadPool.new
|
33
|
-
subject.overflow_policy.should eq :abort
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'raises an exception if given an invalid :overflow_policy' do
|
37
|
-
expect {
|
38
|
-
JavaCachedThreadPool.new(overflow_policy: :bogus)
|
39
|
-
}.to raise_error(ArgumentError)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
if Concurrent::TestHelpers.jruby?
|
4
|
-
|
5
|
-
require_relative 'fixed_thread_pool_shared'
|
6
|
-
|
7
|
-
module Concurrent
|
8
|
-
|
9
|
-
describe JavaFixedThreadPool do
|
10
|
-
|
11
|
-
subject { described_class.new(5, overflow_policy: :discard) }
|
12
|
-
|
13
|
-
after(:each) do
|
14
|
-
subject.kill
|
15
|
-
sleep(0.1)
|
16
|
-
end
|
17
|
-
|
18
|
-
it_should_behave_like :fixed_thread_pool
|
19
|
-
|
20
|
-
context '#initialize' do
|
21
|
-
|
22
|
-
it 'sets :min_length correctly' do
|
23
|
-
subject = JavaFixedThreadPool.new(10)
|
24
|
-
subject.min_length.should eq 10
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'sets :max_length correctly' do
|
28
|
-
subject = JavaFixedThreadPool.new(5)
|
29
|
-
subject.max_length.should eq 5
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'sets :idletime correctly' do
|
33
|
-
subject = JavaFixedThreadPool.new(5)
|
34
|
-
subject.idletime.should eq 0
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'sets :max_queue correctly' do
|
38
|
-
subject = JavaFixedThreadPool.new(5)
|
39
|
-
subject.max_queue.should eq 0
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'sets :overflow_policy correctly' do
|
43
|
-
clazz = java.util.concurrent.ThreadPoolExecutor::DiscardPolicy
|
44
|
-
policy = clazz.new
|
45
|
-
clazz.should_receive(:new).at_least(:once).with(any_args).and_return(policy)
|
46
|
-
|
47
|
-
subject = JavaFixedThreadPool.new(5, overflow_policy: :discard)
|
48
|
-
subject.overflow_policy.should eq :discard
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'defaults :overflow_policy to :abort' do
|
52
|
-
subject = JavaFixedThreadPool.new(5)
|
53
|
-
subject.overflow_policy.should eq :abort
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'raises an exception if given an invalid :overflow_policy' do
|
57
|
-
expect {
|
58
|
-
JavaFixedThreadPool.new(5, overflow_policy: :bogus)
|
59
|
-
}.to raise_error(ArgumentError)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
if Concurrent::TestHelpers.jruby?
|
4
|
-
|
5
|
-
require_relative 'thread_pool_shared'
|
6
|
-
|
7
|
-
module Concurrent
|
8
|
-
|
9
|
-
describe JavaSingleThreadExecutor do
|
10
|
-
|
11
|
-
after(:each) do
|
12
|
-
subject.kill
|
13
|
-
sleep(0.1)
|
14
|
-
end
|
15
|
-
|
16
|
-
subject { JavaSingleThreadExecutor.new }
|
17
|
-
|
18
|
-
it_should_behave_like :executor_service
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
if Concurrent::TestHelpers.jruby?
|
4
|
-
|
5
|
-
require_relative 'thread_pool_executor_shared'
|
6
|
-
|
7
|
-
module Concurrent
|
8
|
-
|
9
|
-
describe JavaThreadPoolExecutor do
|
10
|
-
|
11
|
-
after(:each) do
|
12
|
-
subject.kill
|
13
|
-
sleep(0.1)
|
14
|
-
end
|
15
|
-
|
16
|
-
subject do
|
17
|
-
JavaThreadPoolExecutor.new(
|
18
|
-
min_threads: 2,
|
19
|
-
max_threads: 5,
|
20
|
-
idletime: 60,
|
21
|
-
max_queue: 10,
|
22
|
-
overflow_policy: :discard
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
it_should_behave_like :thread_pool_executor
|
27
|
-
|
28
|
-
context '#overload_policy' do
|
29
|
-
|
30
|
-
specify ':abort maps to AbortPolicy' do
|
31
|
-
clazz = java.util.concurrent.ThreadPoolExecutor::AbortPolicy
|
32
|
-
policy = clazz.new
|
33
|
-
clazz.should_receive(:new).at_least(:once).with(any_args).and_return(policy)
|
34
|
-
JavaThreadPoolExecutor.new(
|
35
|
-
min_threads: 2,
|
36
|
-
max_threads: 5,
|
37
|
-
idletime: 60,
|
38
|
-
max_queue: 10,
|
39
|
-
overflow_policy: :abort
|
40
|
-
)
|
41
|
-
end
|
42
|
-
|
43
|
-
specify ':discard maps to DiscardPolicy' do
|
44
|
-
clazz = java.util.concurrent.ThreadPoolExecutor::DiscardPolicy
|
45
|
-
policy = clazz.new
|
46
|
-
clazz.should_receive(:new).at_least(:once).with(any_args).and_return(policy)
|
47
|
-
JavaThreadPoolExecutor.new(
|
48
|
-
min_threads: 2,
|
49
|
-
max_threads: 5,
|
50
|
-
idletime: 60,
|
51
|
-
max_queue: 10,
|
52
|
-
overflow_policy: :discard
|
53
|
-
)
|
54
|
-
end
|
55
|
-
|
56
|
-
specify ':caller_runs maps to CallerRunsPolicy' do
|
57
|
-
clazz = java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy
|
58
|
-
policy = clazz.new
|
59
|
-
clazz.should_receive(:new).at_least(:once).with(any_args).and_return(policy)
|
60
|
-
JavaThreadPoolExecutor.new(
|
61
|
-
min_threads: 2,
|
62
|
-
max_threads: 5,
|
63
|
-
idletime: 60,
|
64
|
-
max_queue: 10,
|
65
|
-
overflow_policy: :caller_runs
|
66
|
-
)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'global_thread_pool_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe PerThreadExecutor do
|
7
|
-
|
8
|
-
subject { PerThreadExecutor.new }
|
9
|
-
|
10
|
-
it_should_behave_like :global_thread_pool
|
11
|
-
|
12
|
-
context '#post' do
|
13
|
-
|
14
|
-
it 'creates a new thread for a call without arguments' do
|
15
|
-
thread = Thread.new{ nil }
|
16
|
-
Thread.should_receive(:new).with(no_args()).and_return(thread)
|
17
|
-
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
|
18
|
-
subject.post{ nil }
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'executes a call without arguments' do
|
22
|
-
@expected = false
|
23
|
-
subject.post{ @expected = true }
|
24
|
-
sleep(0.1)
|
25
|
-
@expected.should be_true
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'creates a new thread for a call with arguments' do
|
29
|
-
thread = Thread.new{ nil }
|
30
|
-
Thread.should_receive(:new).with(1,2,3).and_return(thread)
|
31
|
-
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
|
32
|
-
subject.post(1,2,3){ nil }
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'executes a call with one argument' do
|
36
|
-
@expected = 0
|
37
|
-
subject.post(1){|one| @expected = one }
|
38
|
-
sleep(0.1)
|
39
|
-
@expected.should == 1
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'executes a call with multiple arguments' do
|
43
|
-
@expected = nil
|
44
|
-
subject.post(1,2,3,4,5){|*args| @expected = args }
|
45
|
-
sleep(0.1)
|
46
|
-
@expected.should eq [1,2,3,4,5]
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'aliases #<<' do
|
50
|
-
thread = Thread.new{ nil }
|
51
|
-
Thread.should_receive(:new).with(no_args()).and_return(thread)
|
52
|
-
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
|
53
|
-
subject << proc{ nil }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'cached_thread_pool_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe RubyCachedThreadPool do
|
7
|
-
|
8
|
-
subject do
|
9
|
-
described_class.new(
|
10
|
-
overflow_policy: :discard,
|
11
|
-
gc_interval: 0
|
12
|
-
)
|
13
|
-
end
|
14
|
-
|
15
|
-
after(:each) do
|
16
|
-
subject.kill
|
17
|
-
sleep(0.1)
|
18
|
-
end
|
19
|
-
|
20
|
-
it_should_behave_like :cached_thread_pool
|
21
|
-
|
22
|
-
context 'garbage collection' do
|
23
|
-
|
24
|
-
subject{ described_class.new(idletime: 1, max_threads: 5, gc_interval: 0) }
|
25
|
-
|
26
|
-
it 'removes from pool any thread that has been idle too long' do
|
27
|
-
subject.instance_variable_set(:@idletime, 1)
|
28
|
-
3.times { subject << proc{ sleep(0.1) } }
|
29
|
-
sleep(0.1)
|
30
|
-
subject.length.should eq 3
|
31
|
-
sleep(2)
|
32
|
-
subject << proc{ nil }
|
33
|
-
sleep(0.1)
|
34
|
-
subject.length.should < 3
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'removes from pool any dead thread' do
|
38
|
-
3.times { subject << proc{ sleep(0.1); raise Exception } }
|
39
|
-
sleep(0.1)
|
40
|
-
subject.length.should eq 3
|
41
|
-
sleep(2)
|
42
|
-
subject << proc{ nil }
|
43
|
-
sleep(0.1)
|
44
|
-
subject.length.should < 3
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'worker creation and caching' do
|
49
|
-
|
50
|
-
subject{ described_class.new(idletime: 1, max_threads: 5) }
|
51
|
-
|
52
|
-
it 'creates new workers when there are none available' do
|
53
|
-
subject.length.should eq 0
|
54
|
-
5.times{ sleep(0.1); subject << proc{ sleep(1) } }
|
55
|
-
sleep(1)
|
56
|
-
subject.length.should eq 5
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'uses existing idle threads' do
|
60
|
-
5.times{ subject << proc{ sleep(0.1) } }
|
61
|
-
sleep(1)
|
62
|
-
subject.length.should >= 5
|
63
|
-
3.times{ subject << proc{ sleep(1) } }
|
64
|
-
sleep(0.1)
|
65
|
-
subject.length.should >= 5
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'fixed_thread_pool_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe RubyFixedThreadPool do
|
7
|
-
|
8
|
-
subject { described_class.new(5, overflow_policy: :discard) }
|
9
|
-
|
10
|
-
after(:each) do
|
11
|
-
subject.kill
|
12
|
-
sleep(0.1)
|
13
|
-
end
|
14
|
-
|
15
|
-
it_should_behave_like :fixed_thread_pool
|
16
|
-
|
17
|
-
context 'exception handling' do
|
18
|
-
|
19
|
-
it 'restarts threads that experience exception' do
|
20
|
-
count = subject.length
|
21
|
-
count.times{ subject << proc{ raise StandardError } }
|
22
|
-
sleep(1)
|
23
|
-
subject.length.should eq count
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'worker creation and caching' do
|
28
|
-
|
29
|
-
it 'creates new workers when there are none available' do
|
30
|
-
pool = described_class.new(5)
|
31
|
-
pool.current_length.should eq 0
|
32
|
-
5.times{ pool << proc{ sleep(1) } }
|
33
|
-
sleep(0.1)
|
34
|
-
pool.current_length.should eq 5
|
35
|
-
pool.kill
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require_relative 'thread_pool_shared'
|
4
|
-
|
5
|
-
module Concurrent
|
6
|
-
|
7
|
-
describe RubySingleThreadExecutor do
|
8
|
-
|
9
|
-
after(:each) do
|
10
|
-
subject.kill
|
11
|
-
sleep(0.1)
|
12
|
-
end
|
13
|
-
|
14
|
-
subject { RubySingleThreadExecutor.new }
|
15
|
-
|
16
|
-
it_should_behave_like :executor_service
|
17
|
-
end
|
18
|
-
end
|
@@ -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
|