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