concurrent-ruby 0.5.0 → 0.6.0.pre.1
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 +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
|