Skip to content

Commit 80b2e46

Browse files
committed
Add Concurrent.executor as an easy access point to global executors
1 parent af23a18 commit 80b2e46

File tree

13 files changed

+170
-181
lines changed

13 files changed

+170
-181
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,3 @@ ext/**/*.bundle
3535
ext/**/*.so
3636
ext/**/*.jar
3737
pkg
38-
*.gem

lib/concurrent/agent.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
require 'concurrent/dereferenceable'
44
require 'concurrent/observable'
5-
require 'concurrent/executor/executor_options'
65
require 'concurrent/utility/timeout'
76
require 'concurrent/logging'
87

@@ -15,7 +14,6 @@ module Concurrent
1514
class Agent
1615
include Dereferenceable
1716
include Observable
18-
include ExecutorOptions
1917
include Logging
2018

2119
attr_reader :timeout, :io_executor, :fast_executor
@@ -42,8 +40,8 @@ def initialize(initial, opts = {})
4240
@validator = Proc.new { |result| true }
4341
self.observers = CopyOnWriteObserverSet.new
4442
@serialized_execution = SerializedExecution.new
45-
@io_executor = get_executor_from(opts) || Concurrent.global_io_executor
46-
@fast_executor = get_executor_from(opts) || Concurrent.global_fast_executor
43+
@io_executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
44+
@fast_executor = Executor.executor_from_options(opts) || Concurrent.global_fast_executor
4745
init_mutex
4846
set_deref_options(opts)
4947
end

lib/concurrent/configuration.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ def self.global_timer_set
105105
GLOBAL_TIMER_SET.value
106106
end
107107

108+
# General access point to global executors.
109+
# @param [Symbol, Executor] maps symbols:
110+
# - :fast - {Concurrent.global_fast_executor}
111+
# - :io - {Concurrent.global_io_executor}
112+
# - :immediate - {Concurrent.global_immediate_executor}
113+
# @return [Executor]
114+
def self.executor(executor_identifier)
115+
Executor.executor(executor_identifier)
116+
end
117+
108118
def self.new_fast_executor(opts = {})
109119
FixedThreadPool.new(
110120
[2, Concurrent.processor_count].max,

lib/concurrent/delay.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'thread'
22
require 'concurrent/configuration'
33
require 'concurrent/obligation'
4-
require 'concurrent/executor/executor_options'
54
require 'concurrent/executor/immediate_executor'
65

76
module Concurrent
@@ -39,7 +38,6 @@ module Concurrent
3938
# @see Concurrent::Dereferenceable
4039
class Delay
4140
include Obligation
42-
include ExecutorOptions
4341

4442
# NOTE: Because the global thread pools are lazy-loaded with these objects
4543
# there is a performance hit every time we post a new task to one of these
@@ -61,7 +59,7 @@ def initialize(opts = {}, &block)
6159

6260
init_obligation
6361
set_deref_options(opts)
64-
@task_executor = get_executor_from(opts)
62+
@task_executor = Executor.executor_from_options(opts)
6563

6664
@task = block
6765
@state = :pending

lib/concurrent/executor/executor.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,65 @@
66
module Concurrent
77

88
module Executor
9+
include Logging
10+
11+
# Get the requested `Executor` based on the values set in the options hash.
12+
#
13+
# @param [Hash] opts the options defining the requested executor
14+
# @option opts [Executor] :executor when set use the given `Executor` instance.
15+
# Three special values are also supported: `:fast` returns the global fast executor,
16+
# `:io` returns the global io executor, and `:immediate` returns a new
17+
# `ImmediateExecutor` object.
18+
#
19+
# @return [Executor, nil] the requested thread pool, or nil when no option specified
20+
#
21+
# @!visibility private
22+
def self.executor_from_options(opts = {}) # :nodoc:
23+
case
24+
when opts.key?(:executor)
25+
if opts[:executor].nil?
26+
nil
27+
else
28+
executor(opts[:executor])
29+
end
30+
when opts.key?(:operation) || opts.key?(:task)
31+
if opts[:operation] == true || opts[:task] == false
32+
Kernel.warn '[DEPRECATED] use `executor: :fast` instead'
33+
return Concurrent.global_fast_executor
34+
end
35+
36+
if opts[:operation] == false || opts[:task] == true
37+
Kernel.warn '[DEPRECATED] use `executor: :io` instead'
38+
return Concurrent.global_io_executor
39+
end
40+
41+
raise ArgumentError.new("executor '#{opts[:executor]}' not recognized")
42+
else
43+
nil
44+
end
45+
end
46+
47+
def self.executor(executor_identifier)
48+
case executor_identifier
49+
when :fast
50+
Concurrent.global_fast_executor
51+
when :io
52+
Concurrent.global_io_executor
53+
when :immediate
54+
Concurrent.global_immediate_executor
55+
when :operation
56+
Kernel.warn '[DEPRECATED] use `executor: :fast` instead'
57+
Concurrent.global_fast_executor
58+
when :task
59+
Kernel.warn '[DEPRECATED] use `executor: :io` instead'
60+
Concurrent.global_io_executor
61+
when Executor
62+
executor_identifier
63+
else
64+
raise ArgumentError, "executor not recognized by '#{executor_identifier}'"
65+
end
66+
end
67+
968
# The policy defining how rejected tasks (tasks received once the
1069
# queue size reaches the configured `max_queue`, or after the
1170
# executor has shut down) are handled. Must be one of the values
@@ -363,4 +422,6 @@ def synchronize
363422
end
364423
end
365424
end
425+
426+
366427
end

lib/concurrent/executor/executor_options.rb

Lines changed: 0 additions & 62 deletions
This file was deleted.

lib/concurrent/executor/ruby_thread_pool_executor.rb

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,11 @@ def ns_shutdown_execution
187187

188188
# @api private
189189
def ns_kill_execution
190-
ns_shutdown_execution
191-
unless stopped_event.wait(1)
192-
@pool.each &:kill
193-
@pool.clear
194-
@ready.clear
195-
# TODO log out unprocessed tasks in queue
196-
end
190+
# TODO log out unprocessed tasks in queue
191+
# TODO try to shutdown first?
192+
@pool.each &:kill
193+
@pool.clear
194+
@ready.clear
197195
end
198196

199197
alias_method :kill_execution, :ns_kill_execution

lib/concurrent/executor/timer_set.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
require 'concurrent/executor/executor'
55
require 'concurrent/executor/single_thread_executor'
66
require 'concurrent/utility/monotonic_time'
7-
require 'concurrent/executor/executor_options'
87

98
module Concurrent
109

@@ -15,7 +14,6 @@ module Concurrent
1514
# @!macro monotonic_clock_warning
1615
class TimerSet
1716
include RubyExecutor
18-
include ExecutorOptions
1917

2018
# Create a new set of timed tasks.
2119
#
@@ -28,7 +26,7 @@ class TimerSet
2826
# `ImmediateExecutor` object.
2927
def initialize(opts = {})
3028
@queue = PriorityQueue.new(order: :min)
31-
@task_executor = get_executor_from(opts) || Concurrent.global_io_executor
29+
@task_executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
3230
@timer_executor = SingleThreadExecutor.new
3331
@condition = Condition.new
3432
init_executor

lib/concurrent/file_map.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module Concurrent
55
edge_lib_files = Dir['lib/concurrent/actor.rb',
66
'lib/concurrent/actor/**/*.rb',
77
'lib/concurrent/channel.rb',
8-
'lib/concurrent/channel/**/*.rb'] & git_files
8+
'lib/concurrent/channel/**/*.rb',
9+
'lib/concurrent/next.rb'] & git_files
910
core_lib_files = all_lib_files - edge_lib_files
1011

1112
FILE_MAP = {

lib/concurrent/future.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
require 'concurrent/ivar'
44
require 'concurrent/executor/safe_task_executor'
5-
require 'concurrent/executor/executor_options'
65

76
module Concurrent
87

@@ -12,7 +11,6 @@ module Concurrent
1211
# @see http://clojuredocs.org/clojure_core/clojure.core/future Clojure's future function
1312
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html java.util.concurrent.Future
1413
class Future < IVar
15-
include ExecutorOptions
1614

1715
# Create a new `Future` in the `:unscheduled` state.
1816
#
@@ -29,7 +27,7 @@ def initialize(opts = {}, &block)
2927
super(IVar::NO_VALUE, opts)
3028
@state = :unscheduled
3129
@task = block
32-
@executor = get_executor_from(opts) || Concurrent.global_io_executor
30+
@executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
3331
@args = get_arguments_from(opts)
3432
end
3533

0 commit comments

Comments
 (0)