concurrent-ruby 0.5.0 → 0.6.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +88 -77
- data/lib/concurrent.rb +17 -2
- data/lib/concurrent/actor.rb +17 -0
- data/lib/concurrent/actor_context.rb +31 -0
- data/lib/concurrent/actor_ref.rb +39 -0
- data/lib/concurrent/agent.rb +12 -3
- data/lib/concurrent/async.rb +290 -0
- data/lib/concurrent/atomic.rb +5 -9
- data/lib/concurrent/cached_thread_pool.rb +39 -137
- data/lib/concurrent/channel/blocking_ring_buffer.rb +60 -0
- data/lib/concurrent/channel/buffered_channel.rb +83 -0
- data/lib/concurrent/channel/channel.rb +11 -0
- data/lib/concurrent/channel/probe.rb +19 -0
- data/lib/concurrent/channel/ring_buffer.rb +54 -0
- data/lib/concurrent/channel/unbuffered_channel.rb +34 -0
- data/lib/concurrent/channel/waitable_list.rb +38 -0
- data/lib/concurrent/configuration.rb +92 -0
- data/lib/concurrent/dataflow.rb +9 -3
- data/lib/concurrent/delay.rb +88 -0
- data/lib/concurrent/exchanger.rb +31 -0
- data/lib/concurrent/fixed_thread_pool.rb +28 -122
- data/lib/concurrent/future.rb +10 -5
- data/lib/concurrent/immediate_executor.rb +3 -2
- data/lib/concurrent/ivar.rb +2 -1
- data/lib/concurrent/java_cached_thread_pool.rb +45 -0
- data/lib/concurrent/java_fixed_thread_pool.rb +37 -0
- data/lib/concurrent/java_thread_pool_executor.rb +194 -0
- data/lib/concurrent/per_thread_executor.rb +23 -0
- data/lib/concurrent/postable.rb +2 -0
- data/lib/concurrent/processor_count.rb +125 -0
- data/lib/concurrent/promise.rb +42 -18
- data/lib/concurrent/ruby_cached_thread_pool.rb +37 -0
- data/lib/concurrent/ruby_fixed_thread_pool.rb +31 -0
- data/lib/concurrent/ruby_thread_pool_executor.rb +268 -0
- data/lib/concurrent/ruby_thread_pool_worker.rb +69 -0
- data/lib/concurrent/simple_actor_ref.rb +124 -0
- data/lib/concurrent/thread_local_var.rb +1 -1
- data/lib/concurrent/thread_pool_executor.rb +30 -0
- data/lib/concurrent/timer_task.rb +13 -10
- data/lib/concurrent/tvar.rb +212 -0
- data/lib/concurrent/utilities.rb +1 -0
- data/lib/concurrent/version.rb +1 -1
- data/spec/concurrent/actor_context_spec.rb +37 -0
- data/spec/concurrent/actor_ref_shared.rb +313 -0
- data/spec/concurrent/actor_spec.rb +9 -1
- data/spec/concurrent/agent_spec.rb +97 -96
- data/spec/concurrent/async_spec.rb +320 -0
- data/spec/concurrent/cached_thread_pool_shared.rb +137 -0
- data/spec/concurrent/channel/blocking_ring_buffer_spec.rb +149 -0
- data/spec/concurrent/channel/buffered_channel_spec.rb +151 -0
- data/spec/concurrent/channel/channel_spec.rb +37 -0
- data/spec/concurrent/channel/probe_spec.rb +49 -0
- data/spec/concurrent/channel/ring_buffer_spec.rb +126 -0
- data/spec/concurrent/channel/unbuffered_channel_spec.rb +132 -0
- data/spec/concurrent/configuration_spec.rb +134 -0
- data/spec/concurrent/dataflow_spec.rb +109 -27
- data/spec/concurrent/delay_spec.rb +77 -0
- data/spec/concurrent/exchanger_spec.rb +66 -0
- data/spec/concurrent/fixed_thread_pool_shared.rb +136 -0
- data/spec/concurrent/future_spec.rb +60 -51
- data/spec/concurrent/global_thread_pool_shared.rb +33 -0
- data/spec/concurrent/immediate_executor_spec.rb +4 -25
- data/spec/concurrent/ivar_spec.rb +36 -23
- data/spec/concurrent/java_cached_thread_pool_spec.rb +64 -0
- data/spec/concurrent/java_fixed_thread_pool_spec.rb +64 -0
- data/spec/concurrent/java_thread_pool_executor_spec.rb +71 -0
- data/spec/concurrent/obligation_shared.rb +32 -20
- data/spec/concurrent/{global_thread_pool_spec.rb → per_thread_executor_spec.rb} +9 -13
- data/spec/concurrent/processor_count_spec.rb +20 -0
- data/spec/concurrent/promise_spec.rb +29 -41
- data/spec/concurrent/ruby_cached_thread_pool_spec.rb +69 -0
- data/spec/concurrent/ruby_fixed_thread_pool_spec.rb +39 -0
- data/spec/concurrent/ruby_thread_pool_executor_spec.rb +183 -0
- data/spec/concurrent/simple_actor_ref_spec.rb +219 -0
- data/spec/concurrent/thread_pool_class_cast_spec.rb +40 -0
- data/spec/concurrent/thread_pool_executor_shared.rb +155 -0
- data/spec/concurrent/thread_pool_shared.rb +98 -36
- data/spec/concurrent/tvar_spec.rb +137 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/functions.rb +4 -0
- metadata +85 -20
- data/lib/concurrent/cached_thread_pool/worker.rb +0 -91
- data/lib/concurrent/channel.rb +0 -63
- data/lib/concurrent/fixed_thread_pool/worker.rb +0 -54
- data/lib/concurrent/global_thread_pool.rb +0 -42
- data/spec/concurrent/cached_thread_pool_spec.rb +0 -101
- data/spec/concurrent/channel_spec.rb +0 -86
- data/spec/concurrent/fixed_thread_pool_spec.rb +0 -92
- data/spec/concurrent/uses_global_thread_pool_shared.rb +0 -64
data/lib/concurrent/channel.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'concurrent/actor'
|
2
|
-
require 'concurrent/stoppable'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
# +Channel+ is a functional programming variation of +Actor+, based very loosely on the
|
7
|
-
# *MailboxProcessor* agent in F#. +Actor+ is used to create objects that receive messages
|
8
|
-
# from other threads then processes those messages based on the behavior of the class.
|
9
|
-
# +Channel+ creates objects that receive messages and processe them using the block
|
10
|
-
# given at construction. +Channel+ is implemented as a subclass of +Actor+ and supports
|
11
|
-
# all message-passing methods of that class. +Channel+ also supports pools with a shared
|
12
|
-
# mailbox.
|
13
|
-
#
|
14
|
-
# @example Basic usage
|
15
|
-
# channel = Concurrent::Channel.new do |msg|
|
16
|
-
# sleep(1)
|
17
|
-
# puts "#{msg}\n"
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# channel.run! => #<Thread:0x007fa123d95fc8 sleep>
|
21
|
-
#
|
22
|
-
# channel.post("Hello, World!") => 1
|
23
|
-
# # wait...
|
24
|
-
# => Hello, World!
|
25
|
-
#
|
26
|
-
# future = channel.post? "Don't Panic." => #<Concurrent::IVar:0x007fa123d6d9d8 @state=:pending...
|
27
|
-
# future.pending? => true
|
28
|
-
# # wait...
|
29
|
-
# => "Don't Panic."
|
30
|
-
# future.fulfilled? => true
|
31
|
-
#
|
32
|
-
# channel.stop => true
|
33
|
-
#
|
34
|
-
# @see http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx Async and Parallel Design Patterns in F#: Agents
|
35
|
-
# @see http://msdn.microsoft.com/en-us/library/ee370357.aspx Control.MailboxProcessor<'Msg> Class (F#)
|
36
|
-
class Channel < Actor
|
37
|
-
include Stoppable
|
38
|
-
|
39
|
-
# Initialize a new object with a block operation to be performed in response
|
40
|
-
# to every received message.
|
41
|
-
#
|
42
|
-
# @yield [message] Removes the next message from the queue and processes it
|
43
|
-
# @yieldparam [Array] msg The next message post to the channel
|
44
|
-
def initialize(&block)
|
45
|
-
raise ArgumentError.new('no block given') unless block_given?
|
46
|
-
super()
|
47
|
-
@task = block
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
def on_stop # :nodoc:
|
53
|
-
before_stop_proc.call if before_stop_proc
|
54
|
-
super
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def act(*message) # :nodoc:
|
60
|
-
return @task.call(*message)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
class FixedThreadPool
|
6
|
-
|
7
|
-
class Worker
|
8
|
-
|
9
|
-
def initialize(queue, parent)
|
10
|
-
@queue = queue
|
11
|
-
@parent = parent
|
12
|
-
@mutex = Mutex.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def dead?
|
16
|
-
return @mutex.synchronize do
|
17
|
-
@thread.nil? ? false : ! @thread.alive?
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def kill
|
22
|
-
@mutex.synchronize do
|
23
|
-
Thread.kill(@thread) unless @thread.nil?
|
24
|
-
@thread = nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def run(thread = Thread.current)
|
29
|
-
@mutex.synchronize do
|
30
|
-
raise StandardError.new('already running') unless @thread.nil?
|
31
|
-
@thread = thread
|
32
|
-
end
|
33
|
-
|
34
|
-
loop do
|
35
|
-
task = @queue.pop
|
36
|
-
if task == :stop
|
37
|
-
@thread = nil
|
38
|
-
@parent.on_worker_exit(self)
|
39
|
-
break
|
40
|
-
end
|
41
|
-
|
42
|
-
@parent.on_start_task(self)
|
43
|
-
begin
|
44
|
-
task.last.call(*task.first)
|
45
|
-
rescue
|
46
|
-
# let it fail
|
47
|
-
ensure
|
48
|
-
@parent.on_end_task(self)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
|
3
|
-
class NullThreadPool
|
4
|
-
|
5
|
-
def self.post(*args)
|
6
|
-
Thread.new(*args) do
|
7
|
-
Thread.current.abort_on_exception = false
|
8
|
-
yield(*args)
|
9
|
-
end
|
10
|
-
return true
|
11
|
-
end
|
12
|
-
|
13
|
-
def post(*args, &block)
|
14
|
-
return NullThreadPool.post(*args, &block)
|
15
|
-
end
|
16
|
-
|
17
|
-
def <<(block)
|
18
|
-
NullThreadPool.post(&block)
|
19
|
-
return self
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module UsesGlobalThreadPool
|
24
|
-
|
25
|
-
def self.included(base)
|
26
|
-
class << base
|
27
|
-
def thread_pool
|
28
|
-
@thread_pool || $GLOBAL_THREAD_POOL
|
29
|
-
end
|
30
|
-
def thread_pool=(pool)
|
31
|
-
if pool == $GLOBAL_THREAD_POOL
|
32
|
-
@thread_pool = nil
|
33
|
-
else
|
34
|
-
@thread_pool = pool
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
$GLOBAL_THREAD_POOL ||= Concurrent::NullThreadPool.new
|
@@ -1,101 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'thread_pool_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe CachedThreadPool do
|
7
|
-
|
8
|
-
subject { CachedThreadPool.new(max_threads: 5) }
|
9
|
-
|
10
|
-
after(:each) do
|
11
|
-
subject.kill
|
12
|
-
sleep(0.1)
|
13
|
-
end
|
14
|
-
|
15
|
-
it_should_behave_like :thread_pool
|
16
|
-
|
17
|
-
context '#initialize' do
|
18
|
-
|
19
|
-
it 'raises an exception when the pool size is less than one' do
|
20
|
-
lambda {
|
21
|
-
CachedThreadPool.new(max: 0)
|
22
|
-
}.should raise_error(ArgumentError)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'raises an exception when the pool size is greater than MAX_POOL_SIZE' do
|
26
|
-
lambda {
|
27
|
-
CachedThreadPool.new(max: CachedThreadPool::MAX_POOL_SIZE + 1)
|
28
|
-
}.should raise_error(ArgumentError)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context '#length' do
|
33
|
-
|
34
|
-
it 'returns zero for a new thread pool' do
|
35
|
-
subject.length.should eq 0
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'returns the length of the subject when running' do
|
39
|
-
5.times{ sleep(0.1); subject << proc{ sleep(1) } }
|
40
|
-
subject.length.should eq 5
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'returns zero once shut down' do
|
44
|
-
subject.shutdown
|
45
|
-
subject.length.should eq 0
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context 'worker creation and caching' do
|
50
|
-
|
51
|
-
it 'creates new workers when there are none available' do
|
52
|
-
subject.length.should eq 0
|
53
|
-
5.times{ sleep(0.1); subject << proc{ sleep } }
|
54
|
-
sleep(1)
|
55
|
-
subject.length.should eq 5
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'uses existing idle threads' do
|
59
|
-
5.times{ subject << proc{ sleep(0.1) } }
|
60
|
-
sleep(1)
|
61
|
-
subject.length.should >= 5
|
62
|
-
3.times{ subject << proc{ sleep } }
|
63
|
-
sleep(0.1)
|
64
|
-
subject.length.should >= 5
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'never creates more than :max_threads threads' do
|
68
|
-
pool = CachedThreadPool.new(max: 5)
|
69
|
-
100.times{ sleep(0.01); pool << proc{ sleep } }
|
70
|
-
sleep(0.1)
|
71
|
-
pool.length.should eq 5
|
72
|
-
pool.kill
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'sets :max_threads to MAX_POOL_SIZE when not given' do
|
76
|
-
CachedThreadPool.new.max_threads.should eq CachedThreadPool::MAX_POOL_SIZE
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'garbage collection' do
|
81
|
-
|
82
|
-
subject{ CachedThreadPool.new(gc_interval: 1, idletime: 1) }
|
83
|
-
|
84
|
-
it 'removes from pool any thread that has been idle too long' do
|
85
|
-
3.times { subject << proc{ sleep(0.1) } }
|
86
|
-
subject.length.should eq 3
|
87
|
-
sleep(2)
|
88
|
-
subject << proc{ nil }
|
89
|
-
subject.length.should < 3
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'removed from pool any dead thread' do
|
93
|
-
3.times { subject << proc{ sleep(0.1); raise Exception } }
|
94
|
-
subject.length.should == 3
|
95
|
-
sleep(2)
|
96
|
-
subject << proc{ nil }
|
97
|
-
subject.length.should < 3
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'postable_shared'
|
3
|
-
require_relative 'runnable_shared'
|
4
|
-
require_relative 'stoppable_shared'
|
5
|
-
|
6
|
-
module Concurrent
|
7
|
-
|
8
|
-
describe Channel do
|
9
|
-
|
10
|
-
context :runnable do
|
11
|
-
subject{ Channel.new{ nil } }
|
12
|
-
it_should_behave_like :runnable
|
13
|
-
end
|
14
|
-
|
15
|
-
context :stoppable do
|
16
|
-
subject do
|
17
|
-
task = Channel.new{ nil }
|
18
|
-
task.run!
|
19
|
-
task
|
20
|
-
end
|
21
|
-
it_should_behave_like :stoppable
|
22
|
-
end
|
23
|
-
|
24
|
-
context :postable do
|
25
|
-
|
26
|
-
let!(:postable_class){ Channel }
|
27
|
-
|
28
|
-
let(:sender) do
|
29
|
-
Channel.new do |*message|
|
30
|
-
if message.first.is_a?(Exception)
|
31
|
-
raise message.first
|
32
|
-
else
|
33
|
-
message.first
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
let(:receiver){ Channel.new{|*message| message.first } }
|
39
|
-
|
40
|
-
it_should_behave_like :postable
|
41
|
-
end
|
42
|
-
|
43
|
-
subject{ Channel.new{ nil } }
|
44
|
-
|
45
|
-
context '#initialize' do
|
46
|
-
|
47
|
-
it 'raises an exception if no block is given' do
|
48
|
-
expect {
|
49
|
-
Channel.new
|
50
|
-
}.to raise_error(ArgumentError)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context '#behavior' do
|
55
|
-
|
56
|
-
it 'calls the block once for each message' do
|
57
|
-
@expected = false
|
58
|
-
channel = Channel.new{ @expected = true }
|
59
|
-
channel.run!
|
60
|
-
channel << 42
|
61
|
-
sleep(0.1)
|
62
|
-
channel.stop
|
63
|
-
@expected.should be_true
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'passes all arguments to the block' do
|
67
|
-
@expected = []
|
68
|
-
channel = Channel.new{|*message| @expected = message }
|
69
|
-
channel.run!
|
70
|
-
channel.post(1,2,3,4,5)
|
71
|
-
sleep(0.1)
|
72
|
-
channel.stop
|
73
|
-
@expected.should eq [1,2,3,4,5]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context '#pool' do
|
78
|
-
|
79
|
-
it 'passes a duplicate of the block to each channel in the pool' do
|
80
|
-
block = proc{ nil }
|
81
|
-
block.should_receive(:dup).exactly(5).times.and_return(proc{ nil })
|
82
|
-
mbox, pool = Channel.pool(5, &block)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'thread_pool_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe FixedThreadPool do
|
7
|
-
|
8
|
-
subject { FixedThreadPool.new(5) }
|
9
|
-
|
10
|
-
after(:each) do
|
11
|
-
subject.kill
|
12
|
-
sleep(0.1)
|
13
|
-
end
|
14
|
-
|
15
|
-
it_should_behave_like :thread_pool
|
16
|
-
|
17
|
-
context '#initialize' do
|
18
|
-
|
19
|
-
it 'raises an exception when the pool length is less than one' do
|
20
|
-
lambda {
|
21
|
-
FixedThreadPool.new(0)
|
22
|
-
}.should raise_error(ArgumentError)
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'raises an exception when the pool length is greater than MAX_POOL_SIZE' do
|
26
|
-
lambda {
|
27
|
-
FixedThreadPool.new(FixedThreadPool::MAX_POOL_SIZE + 1)
|
28
|
-
}.should raise_error(ArgumentError)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context '#length' do
|
33
|
-
|
34
|
-
let(:pool_length) { 3 }
|
35
|
-
subject { FixedThreadPool.new(pool_length) }
|
36
|
-
|
37
|
-
it 'returns zero on start' do
|
38
|
-
subject.shutdown
|
39
|
-
subject.length.should eq 0
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'returns the length of the pool when running' do
|
43
|
-
pool_length.times do |i|
|
44
|
-
subject.post{ sleep }
|
45
|
-
sleep(0.1)
|
46
|
-
subject.length.should eq pool_length
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'returns zero while shutting down' do
|
51
|
-
subject.post{ sleep(1) }
|
52
|
-
subject.shutdown
|
53
|
-
subject.length.should eq 0
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'returns zero once shut down' do
|
57
|
-
subject.shutdown
|
58
|
-
subject.length.should eq 0
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'worker creation and caching' do
|
63
|
-
|
64
|
-
it 'creates new workers when there are none available' do
|
65
|
-
pool = FixedThreadPool.new(5)
|
66
|
-
pool.length.should eq 0
|
67
|
-
5.times{ pool << proc{ sleep } }
|
68
|
-
sleep(0.1)
|
69
|
-
pool.length.should eq 5
|
70
|
-
pool.kill
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'never creates more than :max_threads threads' do
|
74
|
-
pool = FixedThreadPool.new(5)
|
75
|
-
100.times{ pool << proc{ sleep } }
|
76
|
-
sleep(0.1)
|
77
|
-
pool.length.should eq 5
|
78
|
-
pool.kill
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'exception handling' do
|
83
|
-
|
84
|
-
it 'restarts threads that experience exception' do
|
85
|
-
pool = FixedThreadPool.new(5)
|
86
|
-
5.times{ pool << proc{ raise StandardError } }
|
87
|
-
sleep(1)
|
88
|
-
pool.length.should eq 5
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for Concurrent::UsesGlobalThreadPool do
|
4
|
-
|
5
|
-
before(:each) do
|
6
|
-
$GLOBAL_THREAD_POOL = Concurrent::FixedThreadPool.new(1)
|
7
|
-
end
|
8
|
-
|
9
|
-
it 'defaults to the global thread pool' do
|
10
|
-
clazz = Class.new(thread_pool_user)
|
11
|
-
clazz.thread_pool.should eq $GLOBAL_THREAD_POOL
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'sets and gets the thread pool for the class' do
|
15
|
-
pool = Concurrent::NullThreadPool.new
|
16
|
-
thread_pool_user.thread_pool = pool
|
17
|
-
thread_pool_user.thread_pool.should eq pool
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'gives each class its own thread pool' do
|
21
|
-
subject1 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
22
|
-
subject2 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
23
|
-
subject3 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
24
|
-
|
25
|
-
subject1.thread_pool = Concurrent::FixedThreadPool.new(1)
|
26
|
-
subject2.thread_pool = Concurrent::CachedThreadPool.new
|
27
|
-
subject3.thread_pool = Concurrent::NullThreadPool.new
|
28
|
-
|
29
|
-
subject1.thread_pool.should_not eq subject2.thread_pool
|
30
|
-
subject2.thread_pool.should_not eq subject3.thread_pool
|
31
|
-
subject3.thread_pool.should_not eq subject1.thread_pool
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'uses the new global thread pool after the global thread pool is changed' do
|
35
|
-
null_thread_pool = Concurrent::NullThreadPool.new
|
36
|
-
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
37
|
-
|
38
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
39
|
-
thread_pool_user.thread_pool.should_not eq null_thread_pool
|
40
|
-
|
41
|
-
$GLOBAL_THREAD_POOL = null_thread_pool
|
42
|
-
|
43
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
44
|
-
thread_pool_user.thread_pool.should eq null_thread_pool
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'responds to multiple changes in the global thread pool' do
|
48
|
-
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
49
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
50
|
-
|
51
|
-
thread_pool_user.thread_pool = Concurrent::NullThreadPool.new
|
52
|
-
thread_pool_user.thread_pool.should_not eq $GLOBAL_THREAD_POOL
|
53
|
-
|
54
|
-
$GLOBAL_THREAD_POOL = Concurrent::FixedThreadPool.new(1)
|
55
|
-
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
56
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
57
|
-
|
58
|
-
$GLOBAL_THREAD_POOL = Concurrent::CachedThreadPool.new
|
59
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
60
|
-
|
61
|
-
$GLOBAL_THREAD_POOL = Concurrent::NullThreadPool.new
|
62
|
-
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
63
|
-
end
|
64
|
-
end
|