Skip to content

Commit 0c74b69

Browse files
committed
Merge pull request #166 from obrok/indirect-immediate-executor
Create an IndirectImmediateExecutor
2 parents 080c2ae + b3f76a2 commit 0c74b69

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
require 'concurrent/executor/executor'
2+
3+
module Concurrent
4+
# An executor service which runs all operations on a new thread, blocking
5+
# until it completes. Operations are performed in the order they are received
6+
# and no two operations can be performed simultaneously.
7+
#
8+
# This executor service exists mainly for testing an debugging. When used it
9+
# immediately runs every `#post` operation on a new thread, blocking the
10+
# current thread until the operation is complete. This is similar to how the
11+
# ImmediateExecutor works, but the operation has the full stack of the new
12+
# thread at its disposal. This can be helpful when the operations will spawn
13+
# more operations on the same executor and so on - such a situation might
14+
# overflow the single stack in case of an ImmediateExecutor, which is
15+
# inconsistent with how it would behave for a threaded executor.
16+
#
17+
# @note Intended for use primarily in testing and debugging.
18+
class IndirectImmediateExecutor < ImmediateExecutor
19+
# Creates a new executor
20+
def initialize
21+
super
22+
@internal_executor = PerThreadExecutor.new
23+
end
24+
25+
# @!macro executor_method_post
26+
def post(*args, &task)
27+
raise ArgumentError.new("no block given") unless block_given?
28+
return false unless running?
29+
30+
event = Concurrent::Event.new
31+
internal_executor.post do
32+
begin
33+
task.call(*args)
34+
ensure
35+
event.set
36+
end
37+
end
38+
event.wait
39+
40+
true
41+
end
42+
43+
private
44+
attr_reader :internal_executor
45+
end
46+
end

lib/concurrent/executors.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require 'concurrent/executor/cached_thread_pool'
22
require 'concurrent/executor/fixed_thread_pool'
33
require 'concurrent/executor/immediate_executor'
4+
require 'concurrent/executor/indirect_immediate_executor'
45
require 'concurrent/executor/per_thread_executor'
56
require 'concurrent/executor/safe_task_executor'
67
require 'concurrent/executor/single_thread_executor'
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require 'spec_helper'
2+
require_relative 'executor_service_shared'
3+
4+
module Concurrent
5+
6+
describe IndirectImmediateExecutor do
7+
8+
subject { IndirectImmediateExecutor.new }
9+
10+
it_should_behave_like :executor_service
11+
12+
it "runs its tasks synchronously" do
13+
start = Time.now
14+
subject.post { sleep 0.1 }
15+
16+
expect(Time.now - start).to be >= 0.1
17+
end
18+
19+
it "runs the task on a separate thread" do
20+
used_thread = nil
21+
subject.post { used_thread = Thread.current }
22+
23+
expect(used_thread).not_to be(Thread.current)
24+
end
25+
end
26+
end

0 commit comments

Comments
 (0)