Skip to content

Commit b6dd12d

Browse files
petrblahopitr-ch
authored andcommitted
Adds WrappingExecutor class
This can be used for wrapping args and task before passing it to Executor.
1 parent c85e099 commit b6dd12d

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module Concurrent
2+
3+
# Used for wrapping an Executor with Wrapper which can modify arguments or task passed to Executor
4+
class WrappingExecutor < Synchronization::Object
5+
safe_initialization!
6+
7+
include ExecutorService
8+
9+
# @param [Executor] executor Executor to be wrapped
10+
# @yield [*args, &task] Wrapper block which wraps the task with args before it is passed to the Executor
11+
# @yieldparam [Array<Object>] *args Wrapper block will get these from {WrappingExecutor#post} call
12+
# @yieldparam [block] &task Wrapper block will get this from {WrappingExecutor#post} call
13+
# @yieldreturn [Array<Object>] args and task on the last place.
14+
def initialize(executor, &wrapper)
15+
super()
16+
@Wrapper = wrapper
17+
@Executor = executor
18+
end
19+
20+
def post(*args, &task)
21+
*args, task = @Wrapper.call(*args, &task)
22+
@Executor.post(*args, &task)
23+
end
24+
25+
def can_overflow?
26+
@Executor.can_overflow?
27+
end
28+
29+
def serialized?
30+
@Executor.serialized?
31+
end
32+
end
33+
end

lib/concurrent/executors.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
require 'concurrent/executor/single_thread_executor'
1919
require 'concurrent/executor/thread_pool_executor'
2020
require 'concurrent/executor/timer_set'
21+
require 'concurrent/executor/wrapping_executor'
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module Concurrent
2+
RSpec.describe WrappingExecutor do
3+
4+
let(:wrapping_executor) { WrappingExecutor.new(executor, &wrapper) }
5+
let(:executor) { Concurrent.global_fast_executor }
6+
let(:wrapper) { nil }
7+
let(:args) { { foo: 'bar', baz: 42 } }
8+
let(:task) { -> (*args) { return nil } }
9+
10+
subject { wrapping_executor }
11+
12+
it { is_expected.to be_kind_of(WrappingExecutor) }
13+
it { is_expected.to respond_to(:post) }
14+
it { is_expected.to respond_to(:can_overflow?) }
15+
it { is_expected.to respond_to(:serialized?) }
16+
17+
describe '#post' do
18+
context 'with passthrough wrapper' do
19+
let(:wrapper) { -> (*args, &task) { return *args, task } }
20+
21+
it {
22+
expect(executor).to receive(:post).with(args) { |&block| expect(block).to be(task) }
23+
wrapping_executor.post(args, &task)
24+
}
25+
end
26+
27+
context 'with wrapper modifying args' do
28+
let(:wrapper) { -> (*args, &task) { return *args, { xyz: 'abc' }, task } }
29+
30+
it {
31+
expect(executor).to receive(:post).with(args, { xyz: 'abc' }) { |&block| expect(block).to be(task) }
32+
wrapping_executor.post(args, &task)
33+
}
34+
end
35+
36+
context 'with wrapper modifying task' do
37+
let(:wrapper) { -> (*args, &task) { return *args, another_task } }
38+
let(:another_task) { -> (*args) { return true } }
39+
40+
it {
41+
expect(executor).to receive(:post).with(args) { |&block| expect(block).to be(another_task) }
42+
wrapping_executor.post(args, &task)
43+
}
44+
end
45+
46+
end
47+
end
48+
end

0 commit comments

Comments
 (0)