Skip to content

Commit 8bea918

Browse files
committed
Improve behaviour when posting to a shutdown thread pool
If an executor has a handle_overflow method defined, use that in the case where we post to an executor which is not running. If no handle_overflow method is defined (e.g. for the single-thread executor), preserve the current behaviour of returning false. Fixes Github issue #192.
1 parent df20680 commit 8bea918

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

lib/concurrent/executor/executor.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,16 @@ module RubyExecutor
7878
def post(*args, &task)
7979
raise ArgumentError.new('no block given') unless block_given?
8080
mutex.synchronize do
81-
return false unless running?
81+
unless running?
82+
# The executor is shut down - figure out how to reject this task
83+
if self.respond_to?(:handle_overflow, true)
84+
# Reject this task in the same way we'd reject an overflow
85+
return handle_overflow(*args, &task)
86+
else
87+
# No handle_overflow method defined - just return false
88+
return false
89+
end
90+
end
8291
execute(*args, &task)
8392
true
8493
end

spec/concurrent/executor/ruby_thread_pool_executor_spec.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ module Concurrent
8080
}.to raise_error(Concurrent::RejectedExecutionError)
8181
end
8282

83+
specify '#post raises an error when the executor is shutting down' do
84+
expect {
85+
subject.shutdown; subject.post{ sleep(1) }
86+
}.to raise_error(Concurrent::RejectedExecutionError)
87+
end
88+
89+
specify '#<< raises an error when the executor is shutting down' do
90+
expect {
91+
subject.shutdown; subject << proc { sleep(1) }
92+
}.to raise_error(Concurrent::RejectedExecutionError)
93+
end
94+
8395
specify 'a #post task is never executed when the queue is at capacity' do
8496
executed = Concurrent::AtomicFixnum.new(0)
8597
10.times do
@@ -134,6 +146,29 @@ module Concurrent
134146
sleep(0.1)
135147
expect(executed.value).to be < 1000
136148
end
149+
150+
specify 'a #post task is never executed when the executor is shutting down' do
151+
executed = Concurrent::AtomicFixnum.new(0)
152+
subject.shutdown
153+
subject.post{ executed.increment }
154+
sleep(0.1)
155+
expect(executed.value).to be 0
156+
end
157+
158+
specify 'a #<< task is never executed when the executor is shutting down' do
159+
executed = Concurrent::AtomicFixnum.new(0)
160+
subject.shutdown
161+
subject << proc { executed.increment }
162+
sleep(0.1)
163+
expect(executed.value).to be 0
164+
end
165+
166+
specify '#post returns false when the executor is shutting down' do
167+
executed = Concurrent::AtomicFixnum.new(0)
168+
subject.shutdown
169+
ret = subject.post{ executed.increment }
170+
expect(ret).to be false
171+
end
137172
end
138173

139174
context ':caller_runs' do
@@ -165,6 +200,20 @@ module Concurrent
165200
5.times{|i| subject.post{ latch.count_down } }
166201
latch.wait(0.1)
167202
end
203+
204+
specify '#post executes the task on the current thread when the executor is shutting down' do
205+
latch = Concurrent::CountDownLatch.new(1)
206+
subject.shutdown
207+
subject.post{ latch.count_down }
208+
latch.wait(0.1)
209+
end
210+
211+
specify '#<< executes the task on the current thread when the queue is at capacity' do
212+
latch = Concurrent::CountDownLatch.new(1)
213+
subject.shutdown
214+
subject << proc { latch.count_down }
215+
latch.wait(0.1)
216+
end
168217
end
169218
end
170219
end

0 commit comments

Comments
 (0)