Skip to content

Commit d6b9bee

Browse files
committed
Improved specs and docs for ImmediateExecutor and PerThreadExecutor.
1 parent 1241fa2 commit d6b9bee

File tree

3 files changed

+64
-1
lines changed

3 files changed

+64
-1
lines changed

lib/concurrent/executor/immediate_executor.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
require 'concurrent/executor/executor'
33

44
module Concurrent
5+
6+
# An executor service which runs all operations on the current thread,
7+
# blocking as necessary. Operations are performed in the order they are
8+
# received and no two operations can be performed simultaneously.
59
class ImmediateExecutor
610
include SerialExecutor
711

12+
# Creates a new executor
813
def initialize
914
@stopped = Concurrent::Event.new
1015
end

lib/concurrent/executor/per_thread_executor.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
require 'concurrent/atomic/event'
1+
require 'concurrent/atomics'
22
require 'concurrent/executor/executor'
33

44
module Concurrent
55

6+
# An executor service in which every operation spawns a new,
7+
# independently operating thread.
68
class PerThreadExecutor
79
include SerialExecutor
810

11+
# Creates a new executor
912
def initialize
1013
@running = Concurrent::AtomicBoolean.new(true)
1114
@stopped = Concurrent::Event.new
1215
@count = Concurrent::AtomicFixnum.new(0)
1316
end
1417

18+
# @!macro executor_method_post
1519
def self.post(*args)
1620
raise ArgumentError.new('no block given') unless block_given?
1721
Thread.new(*args) do
@@ -21,6 +25,13 @@ def self.post(*args)
2125
true
2226
end
2327

28+
# @!macro executor_method_left_shift
29+
def self.<<(task)
30+
post(&task)
31+
self
32+
end
33+
34+
# @!macro executor_method_post
2435
def post(*args, &task)
2536
raise ArgumentError.new('no block given') unless block_given?
2637
return false unless running?
@@ -36,6 +47,7 @@ def post(*args, &task)
3647
end
3748
end
3849

50+
# @!macro executor_method_left_shift
3951
def <<(task)
4052
post(&task)
4153
self

spec/concurrent/executor/per_thread_executor_spec.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,52 @@ module Concurrent
1111

1212
context '#post' do
1313

14+
subject { PerThreadExecutor.new }
15+
16+
it 'creates a new thread for a call without arguments' do
17+
thread = Thread.new{ nil }
18+
Thread.should_receive(:new).with(no_args()).and_return(thread)
19+
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
20+
subject.post{ nil }
21+
end
22+
23+
it 'executes a call without arguments' do
24+
latch = CountDownLatch.new(1)
25+
subject.post{ latch.count_down }
26+
latch.wait(1).should be_true
27+
end
28+
29+
it 'creates a new thread for a call with arguments' do
30+
thread = Thread.new{ nil }
31+
Thread.should_receive(:new).with(1,2,3).and_return(thread)
32+
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
33+
subject.post(1,2,3){ nil }
34+
end
35+
36+
it 'executes a call with one argument' do
37+
latch = CountDownLatch.new(3)
38+
subject.post(3){|count| count.times{ latch.count_down } }
39+
latch.wait(1).should be_true
40+
end
41+
42+
it 'executes a call with multiple arguments' do
43+
latch = CountDownLatch.new(10)
44+
subject.post(1,2,3,4){|*count| count.reduce(:+).times{ latch.count_down } }
45+
latch.wait(1).should be_true
46+
end
47+
48+
it 'aliases #<<' do
49+
thread = Thread.new{ nil }
50+
Thread.should_receive(:new).with(no_args()).and_return(thread)
51+
Concurrent.configuration.global_task_pool.should_not_receive(:post).with(any_args())
52+
subject << proc{ nil }
53+
end
54+
end
55+
56+
context 'PerThreadExecutor.post' do
57+
58+
subject { PerThreadExecutor }
59+
1460
it 'creates a new thread for a call without arguments' do
1561
thread = Thread.new{ nil }
1662
Thread.should_receive(:new).with(no_args()).and_return(thread)

0 commit comments

Comments
 (0)