concurrent-ruby 0.7.0.rc0-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/LICENSE.txt +21 -0
- data/README.md +166 -0
- data/ext/concurrent_ruby_ext/atomic_reference.c +78 -0
- data/ext/concurrent_ruby_ext/atomic_reference.h +12 -0
- data/ext/concurrent_ruby_ext/extconf.rb +59 -0
- data/ext/concurrent_ruby_ext/rb_concurrent.c +28 -0
- data/lib/2.0/concurrent_ruby_ext.so +0 -0
- data/lib/concurrent.rb +45 -0
- data/lib/concurrent/actress.rb +221 -0
- data/lib/concurrent/actress/ad_hoc.rb +20 -0
- data/lib/concurrent/actress/context.rb +98 -0
- data/lib/concurrent/actress/core.rb +228 -0
- data/lib/concurrent/actress/core_delegations.rb +42 -0
- data/lib/concurrent/actress/envelope.rb +41 -0
- data/lib/concurrent/actress/errors.rb +14 -0
- data/lib/concurrent/actress/reference.rb +64 -0
- data/lib/concurrent/actress/type_check.rb +48 -0
- data/lib/concurrent/agent.rb +232 -0
- data/lib/concurrent/async.rb +319 -0
- data/lib/concurrent/atomic.rb +46 -0
- data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
- data/lib/concurrent/atomic/atomic_fixnum.rb +162 -0
- data/lib/concurrent/atomic/condition.rb +67 -0
- data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +118 -0
- data/lib/concurrent/atomic/copy_on_write_observer_set.rb +117 -0
- data/lib/concurrent/atomic/count_down_latch.rb +116 -0
- data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
- data/lib/concurrent/atomic/event.rb +98 -0
- data/lib/concurrent/atomic/thread_local_var.rb +117 -0
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +7 -0
- data/lib/concurrent/atomic_reference/delegated_update.rb +28 -0
- data/lib/concurrent/atomic_reference/direct_update.rb +28 -0
- data/lib/concurrent/atomic_reference/jruby.rb +8 -0
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +47 -0
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +24 -0
- data/lib/concurrent/atomic_reference/rbx.rb +16 -0
- data/lib/concurrent/atomic_reference/ruby.rb +16 -0
- data/lib/concurrent/atomics.rb +10 -0
- data/lib/concurrent/channel/buffered_channel.rb +85 -0
- data/lib/concurrent/channel/channel.rb +41 -0
- data/lib/concurrent/channel/unbuffered_channel.rb +34 -0
- data/lib/concurrent/channel/waitable_list.rb +40 -0
- data/lib/concurrent/channels.rb +5 -0
- data/lib/concurrent/collection/blocking_ring_buffer.rb +71 -0
- data/lib/concurrent/collection/priority_queue.rb +305 -0
- data/lib/concurrent/collection/ring_buffer.rb +59 -0
- data/lib/concurrent/collections.rb +3 -0
- data/lib/concurrent/configuration.rb +158 -0
- data/lib/concurrent/dataflow.rb +91 -0
- data/lib/concurrent/delay.rb +112 -0
- data/lib/concurrent/dereferenceable.rb +101 -0
- data/lib/concurrent/errors.rb +30 -0
- data/lib/concurrent/exchanger.rb +34 -0
- data/lib/concurrent/executor/cached_thread_pool.rb +44 -0
- data/lib/concurrent/executor/executor.rb +229 -0
- data/lib/concurrent/executor/fixed_thread_pool.rb +33 -0
- data/lib/concurrent/executor/immediate_executor.rb +16 -0
- data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
- data/lib/concurrent/executor/java_fixed_thread_pool.rb +33 -0
- data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
- data/lib/concurrent/executor/java_thread_pool_executor.rb +187 -0
- data/lib/concurrent/executor/per_thread_executor.rb +24 -0
- data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
- data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +32 -0
- data/lib/concurrent/executor/ruby_single_thread_executor.rb +73 -0
- data/lib/concurrent/executor/ruby_thread_pool_executor.rb +286 -0
- data/lib/concurrent/executor/ruby_thread_pool_worker.rb +72 -0
- data/lib/concurrent/executor/safe_task_executor.rb +35 -0
- data/lib/concurrent/executor/serialized_execution.rb +90 -0
- data/lib/concurrent/executor/single_thread_executor.rb +35 -0
- data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
- data/lib/concurrent/executor/timer_set.rb +143 -0
- data/lib/concurrent/executors.rb +9 -0
- data/lib/concurrent/future.rb +124 -0
- data/lib/concurrent/ivar.rb +111 -0
- data/lib/concurrent/logging.rb +17 -0
- data/lib/concurrent/mvar.rb +200 -0
- data/lib/concurrent/obligation.rb +171 -0
- data/lib/concurrent/observable.rb +40 -0
- data/lib/concurrent/options_parser.rb +46 -0
- data/lib/concurrent/promise.rb +169 -0
- data/lib/concurrent/scheduled_task.rb +78 -0
- data/lib/concurrent/supervisor.rb +343 -0
- data/lib/concurrent/timer_task.rb +341 -0
- data/lib/concurrent/tvar.rb +252 -0
- data/lib/concurrent/utilities.rb +3 -0
- data/lib/concurrent/utility/processor_count.rb +150 -0
- data/lib/concurrent/utility/timeout.rb +35 -0
- data/lib/concurrent/utility/timer.rb +21 -0
- data/lib/concurrent/version.rb +3 -0
- data/lib/concurrent_ruby.rb +1 -0
- data/lib/concurrent_ruby_ext.so +0 -0
- data/lib/extension_helper.rb +9 -0
- metadata +141 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'concurrent/executor/ruby_fixed_thread_pool'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
if RUBY_PLATFORM == 'java'
|
6
|
+
require 'concurrent/executor/java_fixed_thread_pool'
|
7
|
+
# @!macro [attach] fixed_thread_pool
|
8
|
+
#
|
9
|
+
# A thread pool with a set number of threads. The number of threads in the pool
|
10
|
+
# is set on construction and remains constant. When all threads are busy new
|
11
|
+
# tasks `#post` to the thread pool are enqueued until a thread becomes available.
|
12
|
+
# Should a thread crash for any reason the thread will immediately be removed
|
13
|
+
# from the pool and replaced.
|
14
|
+
#
|
15
|
+
# The API and behavior of this class are based on Java's `FixedThreadPool`
|
16
|
+
#
|
17
|
+
# @note When running on the JVM (JRuby) this class will inherit from `JavaFixedThreadPool`.
|
18
|
+
# On all other platforms it will inherit from `RubyFixedThreadPool`.
|
19
|
+
#
|
20
|
+
# @see Concurrent::RubyFixedThreadPool
|
21
|
+
# @see Concurrent::JavaFixedThreadPool
|
22
|
+
#
|
23
|
+
# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
|
24
|
+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
|
25
|
+
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
|
26
|
+
class FixedThreadPool < JavaFixedThreadPool
|
27
|
+
end
|
28
|
+
else
|
29
|
+
# @!macro fixed_thread_pool
|
30
|
+
class FixedThreadPool < RubyFixedThreadPool
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
|
3
|
+
require 'concurrent/executor/java_thread_pool_executor'
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
|
7
|
+
# @!macro cached_thread_pool
|
8
|
+
class JavaCachedThreadPool < JavaThreadPoolExecutor
|
9
|
+
|
10
|
+
# Create a new thread pool.
|
11
|
+
#
|
12
|
+
# @param [Hash] opts the options defining pool behavior.
|
13
|
+
# @option opts [Symbol] :overflow_policy (`:abort`) the overflow policy
|
14
|
+
#
|
15
|
+
# @raise [ArgumentError] if `overflow_policy` is not a known policy
|
16
|
+
#
|
17
|
+
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool--
|
18
|
+
def initialize(opts = {})
|
19
|
+
@overflow_policy = opts.fetch(:overflow_policy, :abort)
|
20
|
+
@max_queue = 0
|
21
|
+
|
22
|
+
raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
|
23
|
+
|
24
|
+
@executor = java.util.concurrent.Executors.newCachedThreadPool
|
25
|
+
@executor.setRejectedExecutionHandler(OVERFLOW_POLICIES[@overflow_policy].new)
|
26
|
+
|
27
|
+
set_shutdown_hook
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
|
3
|
+
require 'concurrent/executor/java_thread_pool_executor'
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
|
7
|
+
# @!macro fixed_thread_pool
|
8
|
+
class JavaFixedThreadPool < JavaThreadPoolExecutor
|
9
|
+
|
10
|
+
# Create a new thread pool.
|
11
|
+
#
|
12
|
+
# @param [Hash] opts the options defining pool behavior.
|
13
|
+
# @option opts [Symbol] :overflow_policy (`:abort`) the overflow policy
|
14
|
+
#
|
15
|
+
# @raise [ArgumentError] if `num_threads` is less than or equal to zero
|
16
|
+
# @raise [ArgumentError] if `overflow_policy` is not a known policy
|
17
|
+
#
|
18
|
+
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-
|
19
|
+
def initialize(num_threads, opts = {})
|
20
|
+
@overflow_policy = opts.fetch(:overflow_policy, :abort)
|
21
|
+
@max_queue = 0
|
22
|
+
|
23
|
+
raise ArgumentError.new('number of threads must be greater than zero') if num_threads < 1
|
24
|
+
raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
|
25
|
+
|
26
|
+
@executor = java.util.concurrent.Executors.newFixedThreadPool(num_threads)
|
27
|
+
@executor.setRejectedExecutionHandler(OVERFLOW_POLICIES[@overflow_policy].new)
|
28
|
+
|
29
|
+
set_shutdown_hook
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require_relative 'executor'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
|
6
|
+
# @!macro single_thread_executor
|
7
|
+
class JavaSingleThreadExecutor
|
8
|
+
include JavaExecutor
|
9
|
+
|
10
|
+
# Create a new thread pool.
|
11
|
+
#
|
12
|
+
# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
|
13
|
+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
|
14
|
+
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
|
15
|
+
def initialize(opts = {})
|
16
|
+
@executor = java.util.concurrent.Executors.newSingleThreadExecutor
|
17
|
+
set_shutdown_hook
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require_relative 'executor'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
|
6
|
+
# @!macro thread_pool_executor
|
7
|
+
class JavaThreadPoolExecutor
|
8
|
+
include JavaExecutor
|
9
|
+
|
10
|
+
# Default maximum number of threads that will be created in the pool.
|
11
|
+
DEFAULT_MAX_POOL_SIZE = java.lang.Integer::MAX_VALUE # 2147483647
|
12
|
+
|
13
|
+
# Default minimum number of threads that will be retained in the pool.
|
14
|
+
DEFAULT_MIN_POOL_SIZE = 0
|
15
|
+
|
16
|
+
# Default maximum number of tasks that may be added to the task queue.
|
17
|
+
DEFAULT_MAX_QUEUE_SIZE = 0
|
18
|
+
|
19
|
+
# Default maximum number of seconds a thread in the pool may remain idle
|
20
|
+
# before being reclaimed.
|
21
|
+
DEFAULT_THREAD_IDLETIMEOUT = 60
|
22
|
+
|
23
|
+
# The set of possible overflow policies that may be set at thread pool creation.
|
24
|
+
OVERFLOW_POLICIES = {
|
25
|
+
abort: java.util.concurrent.ThreadPoolExecutor::AbortPolicy,
|
26
|
+
discard: java.util.concurrent.ThreadPoolExecutor::DiscardPolicy,
|
27
|
+
caller_runs: java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
# The maximum number of threads that may be created in the pool.
|
31
|
+
attr_reader :max_length
|
32
|
+
|
33
|
+
# The maximum number of tasks that may be waiting in the work queue at any one time.
|
34
|
+
# When the queue size reaches `max_queue` subsequent tasks will be rejected in
|
35
|
+
# accordance with the configured `overflow_policy`.
|
36
|
+
attr_reader :max_queue
|
37
|
+
|
38
|
+
# The policy defining how rejected tasks (tasks received once the queue size reaches
|
39
|
+
# the configured `max_queue`) are handled. Must be one of the values specified in
|
40
|
+
# `OVERFLOW_POLICIES`.
|
41
|
+
attr_reader :overflow_policy
|
42
|
+
|
43
|
+
# Create a new thread pool.
|
44
|
+
#
|
45
|
+
# @param [Hash] opts the options which configure the thread pool
|
46
|
+
#
|
47
|
+
# @option opts [Integer] :max_threads (DEFAULT_MAX_POOL_SIZE) the maximum
|
48
|
+
# number of threads to be created
|
49
|
+
# @option opts [Integer] :min_threads (DEFAULT_MIN_POOL_SIZE) the minimum
|
50
|
+
# number of threads to be retained
|
51
|
+
# @option opts [Integer] :idletime (DEFAULT_THREAD_IDLETIMEOUT) the maximum
|
52
|
+
# number of seconds a thread may be idle before being reclaimed
|
53
|
+
# @option opts [Integer] :max_queue (DEFAULT_MAX_QUEUE_SIZE) the maximum
|
54
|
+
# number of tasks allowed in the work queue at any one time; a value of
|
55
|
+
# zero means the queue may grow without bounnd
|
56
|
+
# @option opts [Symbol] :overflow_policy (:abort) the policy for handling new
|
57
|
+
# tasks that are received when the queue size has reached `max_queue`
|
58
|
+
#
|
59
|
+
# @raise [ArgumentError] if `:max_threads` is less than one
|
60
|
+
# @raise [ArgumentError] if `:min_threads` is less than zero
|
61
|
+
# @raise [ArgumentError] if `:overflow_policy` is not one of the values specified
|
62
|
+
# in `OVERFLOW_POLICIES`
|
63
|
+
#
|
64
|
+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
|
65
|
+
def initialize(opts = {})
|
66
|
+
min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
|
67
|
+
max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
|
68
|
+
idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
|
69
|
+
@max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
|
70
|
+
@overflow_policy = opts.fetch(:overflow_policy, :abort)
|
71
|
+
|
72
|
+
raise ArgumentError.new('max_threads must be greater than zero') if max_length <= 0
|
73
|
+
raise ArgumentError.new('min_threads cannot be less than zero') if min_length < 0
|
74
|
+
raise ArgumentError.new("#{@overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.keys.include?(@overflow_policy)
|
75
|
+
|
76
|
+
if min_length == 0 && @max_queue == 0
|
77
|
+
queue = java.util.concurrent.SynchronousQueue.new
|
78
|
+
elsif @max_queue == 0
|
79
|
+
queue = java.util.concurrent.LinkedBlockingQueue.new
|
80
|
+
else
|
81
|
+
queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
|
82
|
+
end
|
83
|
+
|
84
|
+
@executor = java.util.concurrent.ThreadPoolExecutor.new(
|
85
|
+
min_length, max_length,
|
86
|
+
idletime, java.util.concurrent.TimeUnit::SECONDS,
|
87
|
+
queue, OVERFLOW_POLICIES[@overflow_policy].new)
|
88
|
+
|
89
|
+
set_shutdown_hook
|
90
|
+
end
|
91
|
+
|
92
|
+
def can_overflow?
|
93
|
+
@max_queue != 0
|
94
|
+
end
|
95
|
+
|
96
|
+
# The minimum number of threads that may be retained in the pool.
|
97
|
+
#
|
98
|
+
# @return [Integer] the min_length
|
99
|
+
def min_length
|
100
|
+
@executor.getCorePoolSize
|
101
|
+
end
|
102
|
+
|
103
|
+
# The maximum number of threads that may be created in the pool.
|
104
|
+
#
|
105
|
+
# @return [Integer] the max_length
|
106
|
+
def max_length
|
107
|
+
@executor.getMaximumPoolSize
|
108
|
+
end
|
109
|
+
|
110
|
+
# The number of threads currently in the pool.
|
111
|
+
#
|
112
|
+
# @return [Integer] the length
|
113
|
+
def length
|
114
|
+
@executor.getPoolSize
|
115
|
+
end
|
116
|
+
alias_method :current_length, :length
|
117
|
+
|
118
|
+
# The largest number of threads that have been created in the pool since construction.
|
119
|
+
#
|
120
|
+
# @return [Integer] the largest_length
|
121
|
+
def largest_length
|
122
|
+
@executor.getLargestPoolSize
|
123
|
+
end
|
124
|
+
|
125
|
+
# The number of tasks that have been scheduled for execution on the pool since construction.
|
126
|
+
#
|
127
|
+
# @return [Integer] the scheduled_task_count
|
128
|
+
def scheduled_task_count
|
129
|
+
@executor.getTaskCount
|
130
|
+
end
|
131
|
+
|
132
|
+
# The number of tasks that have been completed by the pool since construction.
|
133
|
+
#
|
134
|
+
# @return [Integer] the completed_task_count
|
135
|
+
def completed_task_count
|
136
|
+
@executor.getCompletedTaskCount
|
137
|
+
end
|
138
|
+
|
139
|
+
# The number of seconds that a thread may be idle before being reclaimed.
|
140
|
+
#
|
141
|
+
# @return [Integer] the idletime
|
142
|
+
def idletime
|
143
|
+
@executor.getKeepAliveTime(java.util.concurrent.TimeUnit::SECONDS)
|
144
|
+
end
|
145
|
+
|
146
|
+
# The number of tasks in the queue awaiting execution.
|
147
|
+
#
|
148
|
+
# @return [Integer] the queue_length
|
149
|
+
def queue_length
|
150
|
+
@executor.getQueue.size
|
151
|
+
end
|
152
|
+
|
153
|
+
# Number of tasks that may be enqueued before reaching `max_queue` and rejecting
|
154
|
+
# new tasks. A value of -1 indicates that the queue may grow without bound.
|
155
|
+
#
|
156
|
+
# @return [Integer] the remaining_capacity
|
157
|
+
def remaining_capacity
|
158
|
+
@max_queue == 0 ? -1 : @executor.getQueue.remainingCapacity
|
159
|
+
end
|
160
|
+
|
161
|
+
# This method is deprecated and will be removed soon.
|
162
|
+
# This method is supost to return the threads status, but Java API doesn't
|
163
|
+
# provide a way to get the thread status. So we return an empty Array instead.
|
164
|
+
def status
|
165
|
+
warn '[DEPRECATED] `status` is deprecated and will be removed soon.'
|
166
|
+
warn "Calls to `status` return an empty Array. Java ThreadPoolExecutor does not provide thread's status."
|
167
|
+
[]
|
168
|
+
end
|
169
|
+
|
170
|
+
# Is the thread pool running?
|
171
|
+
#
|
172
|
+
# @return [Boolean] `true` when running, `false` when shutting down or shutdown
|
173
|
+
def running?
|
174
|
+
super && ! @executor.isTerminating
|
175
|
+
end
|
176
|
+
|
177
|
+
# Begin an orderly shutdown. Tasks already in the queue will be executed,
|
178
|
+
# but no new tasks will be accepted. Has no additional effect if the
|
179
|
+
# thread pool is not running.
|
180
|
+
def shutdown
|
181
|
+
super
|
182
|
+
@executor.getQueue.clear
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
class PerThreadExecutor
|
4
|
+
include Executor
|
5
|
+
|
6
|
+
def self.post(*args)
|
7
|
+
raise ArgumentError.new('no block given') unless block_given?
|
8
|
+
Thread.new(*args) do
|
9
|
+
Thread.current.abort_on_exception = false
|
10
|
+
yield(*args)
|
11
|
+
end
|
12
|
+
return true
|
13
|
+
end
|
14
|
+
|
15
|
+
def post(*args, &task)
|
16
|
+
return PerThreadExecutor.post(*args, &task)
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(task)
|
20
|
+
PerThreadExecutor.post(&task)
|
21
|
+
return self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'concurrent/executor/ruby_thread_pool_executor'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# @!macro cached_thread_pool
|
6
|
+
class RubyCachedThreadPool < RubyThreadPoolExecutor
|
7
|
+
|
8
|
+
# Create a new thread pool.
|
9
|
+
#
|
10
|
+
# @param [Hash] opts the options defining pool behavior.
|
11
|
+
# number of seconds a thread may be idle before it is reclaimed
|
12
|
+
#
|
13
|
+
# @raise [ArgumentError] if `overflow_policy` is not a known policy
|
14
|
+
def initialize(opts = {})
|
15
|
+
overflow_policy = opts.fetch(:overflow_policy, :abort)
|
16
|
+
|
17
|
+
raise ArgumentError.new("#{overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.include?(overflow_policy)
|
18
|
+
|
19
|
+
opts = opts.merge(
|
20
|
+
min_threads: 0,
|
21
|
+
max_threads: DEFAULT_MAX_POOL_SIZE,
|
22
|
+
num_threads: overflow_policy,
|
23
|
+
max_queue: DEFAULT_MAX_QUEUE_SIZE,
|
24
|
+
idletime: DEFAULT_THREAD_IDLETIMEOUT
|
25
|
+
)
|
26
|
+
super(opts)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'concurrent/executor/ruby_thread_pool_executor'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# @!macro fixed_thread_pool
|
6
|
+
class RubyFixedThreadPool < RubyThreadPoolExecutor
|
7
|
+
|
8
|
+
# Create a new thread pool.
|
9
|
+
#
|
10
|
+
# @param [Integer] num_threads the number of threads to allocate
|
11
|
+
# @param [Hash] opts the options defining pool behavior.
|
12
|
+
# @option opts [Symbol] :overflow_policy (`:abort`) the overflow policy
|
13
|
+
#
|
14
|
+
# @raise [ArgumentError] if `num_threads` is less than or equal to zero
|
15
|
+
# @raise [ArgumentError] if `overflow_policy` is not a known policy
|
16
|
+
def initialize(num_threads, opts = {})
|
17
|
+
overflow_policy = opts.fetch(:overflow_policy, :abort)
|
18
|
+
|
19
|
+
raise ArgumentError.new('number of threads must be greater than zero') if num_threads < 1
|
20
|
+
raise ArgumentError.new("#{overflow_policy} is not a valid overflow policy") unless OVERFLOW_POLICIES.include?(overflow_policy)
|
21
|
+
|
22
|
+
opts = opts.merge(
|
23
|
+
min_threads: num_threads,
|
24
|
+
max_threads: num_threads,
|
25
|
+
num_threads: overflow_policy,
|
26
|
+
max_queue: DEFAULT_MAX_QUEUE_SIZE,
|
27
|
+
idletime: 0
|
28
|
+
)
|
29
|
+
super(opts)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require_relative 'executor'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# @!macro single_thread_executor
|
6
|
+
class RubySingleThreadExecutor
|
7
|
+
include RubyExecutor
|
8
|
+
|
9
|
+
# Create a new thread pool.
|
10
|
+
#
|
11
|
+
# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
|
12
|
+
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
|
13
|
+
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
|
14
|
+
def initialize(opts = {})
|
15
|
+
@queue = Queue.new
|
16
|
+
@thread = nil
|
17
|
+
init_executor
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
# @!visibility private
|
23
|
+
def execute(*args, &task)
|
24
|
+
supervise
|
25
|
+
@queue << [args, task]
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!visibility private
|
29
|
+
def shutdown_execution
|
30
|
+
@queue << :stop
|
31
|
+
stopped_event.set unless alive?
|
32
|
+
end
|
33
|
+
|
34
|
+
# @!visibility private
|
35
|
+
def kill_execution
|
36
|
+
@queue.clear
|
37
|
+
@thread.kill if alive?
|
38
|
+
end
|
39
|
+
|
40
|
+
# @!visibility private
|
41
|
+
def alive?
|
42
|
+
@thread && @thread.alive?
|
43
|
+
end
|
44
|
+
|
45
|
+
# @!visibility private
|
46
|
+
def supervise
|
47
|
+
@thread = new_worker_thread unless alive?
|
48
|
+
end
|
49
|
+
|
50
|
+
# @!visibility private
|
51
|
+
def new_worker_thread
|
52
|
+
Thread.new do
|
53
|
+
Thread.current.abort_on_exception = false
|
54
|
+
work
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @!visibility private
|
59
|
+
def work
|
60
|
+
loop do
|
61
|
+
task = @queue.pop
|
62
|
+
break if task == :stop
|
63
|
+
begin
|
64
|
+
task.last.call(*task.first)
|
65
|
+
rescue => ex
|
66
|
+
# let it fail
|
67
|
+
log DEBUG, ex
|
68
|
+
end
|
69
|
+
end
|
70
|
+
stopped_event.set
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|