o-concurrent-ruby 1.1.11
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 +7 -0
- data/CHANGELOG.md +542 -0
- data/Gemfile +37 -0
- data/LICENSE.txt +21 -0
- data/README.md +404 -0
- data/Rakefile +307 -0
- data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +189 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
- data/lib/concurrent-ruby/concurrent/agent.rb +587 -0
- data/lib/concurrent-ruby/concurrent/array.rb +66 -0
- data/lib/concurrent-ruby/concurrent/async.rb +449 -0
- data/lib/concurrent-ruby/concurrent/atom.rb +222 -0
- data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +66 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +126 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +143 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +205 -0
- data/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb +100 -0
- data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +128 -0
- data/lib/concurrent-ruby/concurrent/atomic/event.rb +109 -0
- data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +42 -0
- data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +37 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +62 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +75 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +44 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +131 -0
- data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +254 -0
- data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +377 -0
- data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +181 -0
- data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +166 -0
- data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +104 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +56 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb +28 -0
- data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
- data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +107 -0
- data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +111 -0
- data/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb +84 -0
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
- data/lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb +927 -0
- data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +66 -0
- data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +140 -0
- data/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb +82 -0
- data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
- data/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb +143 -0
- data/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb +160 -0
- data/lib/concurrent-ruby/concurrent/concern/deprecation.rb +34 -0
- data/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb +73 -0
- data/lib/concurrent-ruby/concurrent/concern/logging.rb +32 -0
- data/lib/concurrent-ruby/concurrent/concern/obligation.rb +220 -0
- data/lib/concurrent-ruby/concurrent/concern/observable.rb +110 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +188 -0
- data/lib/concurrent-ruby/concurrent/constants.rb +8 -0
- data/lib/concurrent-ruby/concurrent/dataflow.rb +81 -0
- data/lib/concurrent-ruby/concurrent/delay.rb +199 -0
- data/lib/concurrent-ruby/concurrent/errors.rb +69 -0
- data/lib/concurrent-ruby/concurrent/exchanger.rb +352 -0
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +131 -0
- data/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb +62 -0
- data/lib/concurrent-ruby/concurrent/executor/executor_service.rb +185 -0
- data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +220 -0
- data/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb +66 -0
- data/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb +44 -0
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +103 -0
- data/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb +30 -0
- data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +140 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb +82 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb +21 -0
- data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +368 -0
- data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +35 -0
- data/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb +34 -0
- data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +107 -0
- data/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb +28 -0
- data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +100 -0
- data/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb +57 -0
- data/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb +88 -0
- data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +172 -0
- data/lib/concurrent-ruby/concurrent/executors.rb +20 -0
- data/lib/concurrent-ruby/concurrent/future.rb +141 -0
- data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
- data/lib/concurrent-ruby/concurrent/immutable_struct.rb +101 -0
- data/lib/concurrent-ruby/concurrent/ivar.rb +207 -0
- data/lib/concurrent-ruby/concurrent/map.rb +346 -0
- data/lib/concurrent-ruby/concurrent/maybe.rb +229 -0
- data/lib/concurrent-ruby/concurrent/mutable_struct.rb +239 -0
- data/lib/concurrent-ruby/concurrent/mvar.rb +242 -0
- data/lib/concurrent-ruby/concurrent/options.rb +42 -0
- data/lib/concurrent-ruby/concurrent/promise.rb +580 -0
- data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
- data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
- data/lib/concurrent-ruby/concurrent/scheduled_task.rb +331 -0
- data/lib/concurrent-ruby/concurrent/set.rb +74 -0
- data/lib/concurrent-ruby/concurrent/settable_struct.rb +139 -0
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +98 -0
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +24 -0
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb +171 -0
- data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +60 -0
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +13 -0
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +45 -0
- data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +72 -0
- data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +44 -0
- data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +88 -0
- data/lib/concurrent-ruby/concurrent/synchronization/object.rb +183 -0
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +71 -0
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +49 -0
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
- data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization.rb +30 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +50 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb +74 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +118 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +88 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb +38 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb +246 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb +75 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb +50 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util.rb +16 -0
- data/lib/concurrent-ruby/concurrent/timer_task.rb +311 -0
- data/lib/concurrent-ruby/concurrent/tuple.rb +86 -0
- data/lib/concurrent-ruby/concurrent/tvar.rb +221 -0
- data/lib/concurrent-ruby/concurrent/utility/engine.rb +56 -0
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
- data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +53 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +130 -0
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
- data/lib/concurrent-ruby/concurrent.rb +134 -0
- metadata +192 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'concurrent/executor/immediate_executor'
|
2
|
+
require 'concurrent/executor/simple_executor_service'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
# An executor service which runs all operations on a new thread, blocking
|
6
|
+
# until it completes. Operations are performed in the order they are received
|
7
|
+
# and no two operations can be performed simultaneously.
|
8
|
+
#
|
9
|
+
# This executor service exists mainly for testing an debugging. When used it
|
10
|
+
# immediately runs every `#post` operation on a new thread, blocking the
|
11
|
+
# current thread until the operation is complete. This is similar to how the
|
12
|
+
# ImmediateExecutor works, but the operation has the full stack of the new
|
13
|
+
# thread at its disposal. This can be helpful when the operations will spawn
|
14
|
+
# more operations on the same executor and so on - such a situation might
|
15
|
+
# overflow the single stack in case of an ImmediateExecutor, which is
|
16
|
+
# inconsistent with how it would behave for a threaded executor.
|
17
|
+
#
|
18
|
+
# @note Intended for use primarily in testing and debugging.
|
19
|
+
class IndirectImmediateExecutor < ImmediateExecutor
|
20
|
+
# Creates a new executor
|
21
|
+
def initialize
|
22
|
+
super
|
23
|
+
@internal_executor = SimpleExecutorService.new
|
24
|
+
end
|
25
|
+
|
26
|
+
# @!macro executor_service_method_post
|
27
|
+
def post(*args, &task)
|
28
|
+
raise ArgumentError.new("no block given") unless block_given?
|
29
|
+
return false unless running?
|
30
|
+
|
31
|
+
event = Concurrent::Event.new
|
32
|
+
@internal_executor.post do
|
33
|
+
begin
|
34
|
+
task.call(*args)
|
35
|
+
ensure
|
36
|
+
event.set
|
37
|
+
end
|
38
|
+
end
|
39
|
+
event.wait
|
40
|
+
|
41
|
+
true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
if Concurrent.on_jruby?
|
2
|
+
|
3
|
+
require 'concurrent/errors'
|
4
|
+
require 'concurrent/utility/engine'
|
5
|
+
require 'concurrent/executor/abstract_executor_service'
|
6
|
+
|
7
|
+
module Concurrent
|
8
|
+
|
9
|
+
# @!macro abstract_executor_service_public_api
|
10
|
+
# @!visibility private
|
11
|
+
class JavaExecutorService < AbstractExecutorService
|
12
|
+
java_import 'java.lang.Runnable'
|
13
|
+
|
14
|
+
FALLBACK_POLICY_CLASSES = {
|
15
|
+
abort: java.util.concurrent.ThreadPoolExecutor::AbortPolicy,
|
16
|
+
discard: java.util.concurrent.ThreadPoolExecutor::DiscardPolicy,
|
17
|
+
caller_runs: java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy
|
18
|
+
}.freeze
|
19
|
+
private_constant :FALLBACK_POLICY_CLASSES
|
20
|
+
|
21
|
+
def post(*args, &task)
|
22
|
+
raise ArgumentError.new('no block given') unless block_given?
|
23
|
+
return fallback_action(*args, &task).call unless running?
|
24
|
+
@executor.submit Job.new(args, task)
|
25
|
+
true
|
26
|
+
rescue Java::JavaUtilConcurrent::RejectedExecutionException
|
27
|
+
raise RejectedExecutionError
|
28
|
+
end
|
29
|
+
|
30
|
+
def wait_for_termination(timeout = nil)
|
31
|
+
if timeout.nil?
|
32
|
+
ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok
|
33
|
+
true
|
34
|
+
else
|
35
|
+
@executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def shutdown
|
40
|
+
synchronize do
|
41
|
+
@executor.shutdown
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def kill
|
47
|
+
synchronize do
|
48
|
+
@executor.shutdownNow
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def ns_running?
|
56
|
+
!(ns_shuttingdown? || ns_shutdown?)
|
57
|
+
end
|
58
|
+
|
59
|
+
def ns_shuttingdown?
|
60
|
+
if @executor.respond_to? :isTerminating
|
61
|
+
@executor.isTerminating
|
62
|
+
else
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def ns_shutdown?
|
68
|
+
@executor.isShutdown || @executor.isTerminated
|
69
|
+
end
|
70
|
+
|
71
|
+
class Job
|
72
|
+
include Runnable
|
73
|
+
def initialize(args, block)
|
74
|
+
@args = args
|
75
|
+
@block = block
|
76
|
+
end
|
77
|
+
|
78
|
+
def run
|
79
|
+
@block.call(*@args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
private_constant :Job
|
83
|
+
end
|
84
|
+
|
85
|
+
class DaemonThreadFactory
|
86
|
+
# hide include from YARD
|
87
|
+
send :include, java.util.concurrent.ThreadFactory
|
88
|
+
|
89
|
+
def initialize(daemonize = true)
|
90
|
+
@daemonize = daemonize
|
91
|
+
end
|
92
|
+
|
93
|
+
def newThread(runnable)
|
94
|
+
thread = java.util.concurrent.Executors.defaultThreadFactory().newThread(runnable)
|
95
|
+
thread.setDaemon(@daemonize)
|
96
|
+
return thread
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private_constant :DaemonThreadFactory
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
if Concurrent.on_jruby?
|
2
|
+
|
3
|
+
require 'concurrent/executor/java_executor_service'
|
4
|
+
require 'concurrent/executor/serial_executor_service'
|
5
|
+
|
6
|
+
module Concurrent
|
7
|
+
|
8
|
+
# @!macro single_thread_executor
|
9
|
+
# @!macro abstract_executor_service_public_api
|
10
|
+
# @!visibility private
|
11
|
+
class JavaSingleThreadExecutor < JavaExecutorService
|
12
|
+
include SerialExecutorService
|
13
|
+
|
14
|
+
# @!macro single_thread_executor_method_initialize
|
15
|
+
def initialize(opts = {})
|
16
|
+
super(opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def ns_initialize(opts)
|
22
|
+
@executor = java.util.concurrent.Executors.newSingleThreadExecutor(
|
23
|
+
DaemonThreadFactory.new(ns_auto_terminate?)
|
24
|
+
)
|
25
|
+
@fallback_policy = opts.fetch(:fallback_policy, :discard)
|
26
|
+
raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.keys.include?(@fallback_policy)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
if Concurrent.on_jruby?
|
2
|
+
|
3
|
+
require 'concurrent/executor/java_executor_service'
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
|
7
|
+
# @!macro thread_pool_executor
|
8
|
+
# @!macro thread_pool_options
|
9
|
+
# @!visibility private
|
10
|
+
class JavaThreadPoolExecutor < JavaExecutorService
|
11
|
+
|
12
|
+
# @!macro thread_pool_executor_constant_default_max_pool_size
|
13
|
+
DEFAULT_MAX_POOL_SIZE = java.lang.Integer::MAX_VALUE # 2147483647
|
14
|
+
|
15
|
+
# @!macro thread_pool_executor_constant_default_min_pool_size
|
16
|
+
DEFAULT_MIN_POOL_SIZE = 0
|
17
|
+
|
18
|
+
# @!macro thread_pool_executor_constant_default_max_queue_size
|
19
|
+
DEFAULT_MAX_QUEUE_SIZE = 0
|
20
|
+
|
21
|
+
# @!macro thread_pool_executor_constant_default_thread_timeout
|
22
|
+
DEFAULT_THREAD_IDLETIMEOUT = 60
|
23
|
+
|
24
|
+
# @!macro thread_pool_executor_constant_default_synchronous
|
25
|
+
DEFAULT_SYNCHRONOUS = false
|
26
|
+
|
27
|
+
# @!macro thread_pool_executor_attr_reader_max_length
|
28
|
+
attr_reader :max_length
|
29
|
+
|
30
|
+
# @!macro thread_pool_executor_attr_reader_max_queue
|
31
|
+
attr_reader :max_queue
|
32
|
+
|
33
|
+
# @!macro thread_pool_executor_attr_reader_synchronous
|
34
|
+
attr_reader :synchronous
|
35
|
+
|
36
|
+
# @!macro thread_pool_executor_method_initialize
|
37
|
+
def initialize(opts = {})
|
38
|
+
super(opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @!macro executor_service_method_can_overflow_question
|
42
|
+
def can_overflow?
|
43
|
+
@max_queue != 0
|
44
|
+
end
|
45
|
+
|
46
|
+
# @!macro thread_pool_executor_attr_reader_min_length
|
47
|
+
def min_length
|
48
|
+
@executor.getCorePoolSize
|
49
|
+
end
|
50
|
+
|
51
|
+
# @!macro thread_pool_executor_attr_reader_max_length
|
52
|
+
def max_length
|
53
|
+
@executor.getMaximumPoolSize
|
54
|
+
end
|
55
|
+
|
56
|
+
# @!macro thread_pool_executor_attr_reader_length
|
57
|
+
def length
|
58
|
+
@executor.getPoolSize
|
59
|
+
end
|
60
|
+
|
61
|
+
# @!macro thread_pool_executor_attr_reader_largest_length
|
62
|
+
def largest_length
|
63
|
+
@executor.getLargestPoolSize
|
64
|
+
end
|
65
|
+
|
66
|
+
# @!macro thread_pool_executor_attr_reader_scheduled_task_count
|
67
|
+
def scheduled_task_count
|
68
|
+
@executor.getTaskCount
|
69
|
+
end
|
70
|
+
|
71
|
+
# @!macro thread_pool_executor_attr_reader_completed_task_count
|
72
|
+
def completed_task_count
|
73
|
+
@executor.getCompletedTaskCount
|
74
|
+
end
|
75
|
+
|
76
|
+
# @!macro thread_pool_executor_attr_reader_idletime
|
77
|
+
def idletime
|
78
|
+
@executor.getKeepAliveTime(java.util.concurrent.TimeUnit::SECONDS)
|
79
|
+
end
|
80
|
+
|
81
|
+
# @!macro thread_pool_executor_attr_reader_queue_length
|
82
|
+
def queue_length
|
83
|
+
@executor.getQueue.size
|
84
|
+
end
|
85
|
+
|
86
|
+
# @!macro thread_pool_executor_attr_reader_remaining_capacity
|
87
|
+
def remaining_capacity
|
88
|
+
@max_queue == 0 ? -1 : @executor.getQueue.remainingCapacity
|
89
|
+
end
|
90
|
+
|
91
|
+
# @!macro executor_service_method_running_question
|
92
|
+
def running?
|
93
|
+
super && !@executor.isTerminating
|
94
|
+
end
|
95
|
+
|
96
|
+
# @!macro thread_pool_executor_method_prune_pool
|
97
|
+
def prune_pool
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def ns_initialize(opts)
|
103
|
+
min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
|
104
|
+
max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
|
105
|
+
idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
|
106
|
+
@max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
|
107
|
+
@synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
|
108
|
+
@fallback_policy = opts.fetch(:fallback_policy, :abort)
|
109
|
+
|
110
|
+
raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
|
111
|
+
raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
|
112
|
+
raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE
|
113
|
+
raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE
|
114
|
+
raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length
|
115
|
+
raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy)
|
116
|
+
|
117
|
+
if @max_queue == 0
|
118
|
+
if @synchronous
|
119
|
+
queue = java.util.concurrent.SynchronousQueue.new
|
120
|
+
else
|
121
|
+
queue = java.util.concurrent.LinkedBlockingQueue.new
|
122
|
+
end
|
123
|
+
else
|
124
|
+
queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
|
125
|
+
end
|
126
|
+
|
127
|
+
@executor = java.util.concurrent.ThreadPoolExecutor.new(
|
128
|
+
min_length,
|
129
|
+
max_length,
|
130
|
+
idletime,
|
131
|
+
java.util.concurrent.TimeUnit::SECONDS,
|
132
|
+
queue,
|
133
|
+
DaemonThreadFactory.new(ns_auto_terminate?),
|
134
|
+
FALLBACK_POLICY_CLASSES[@fallback_policy].new)
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'concurrent/executor/abstract_executor_service'
|
2
|
+
require 'concurrent/atomic/event'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
|
6
|
+
# @!macro abstract_executor_service_public_api
|
7
|
+
# @!visibility private
|
8
|
+
class RubyExecutorService < AbstractExecutorService
|
9
|
+
safe_initialization!
|
10
|
+
|
11
|
+
def initialize(*args, &block)
|
12
|
+
super
|
13
|
+
@StopEvent = Event.new
|
14
|
+
@StoppedEvent = Event.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def post(*args, &task)
|
18
|
+
raise ArgumentError.new('no block given') unless block_given?
|
19
|
+
deferred_action = synchronize {
|
20
|
+
if running?
|
21
|
+
ns_execute(*args, &task)
|
22
|
+
else
|
23
|
+
fallback_action(*args, &task)
|
24
|
+
end
|
25
|
+
}
|
26
|
+
if deferred_action
|
27
|
+
deferred_action.call
|
28
|
+
else
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def shutdown
|
34
|
+
synchronize do
|
35
|
+
break unless running?
|
36
|
+
stop_event.set
|
37
|
+
ns_shutdown_execution
|
38
|
+
end
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
def kill
|
43
|
+
synchronize do
|
44
|
+
break if shutdown?
|
45
|
+
stop_event.set
|
46
|
+
ns_kill_execution
|
47
|
+
stopped_event.set
|
48
|
+
end
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def wait_for_termination(timeout = nil)
|
53
|
+
stopped_event.wait(timeout)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def stop_event
|
59
|
+
@StopEvent
|
60
|
+
end
|
61
|
+
|
62
|
+
def stopped_event
|
63
|
+
@StoppedEvent
|
64
|
+
end
|
65
|
+
|
66
|
+
def ns_shutdown_execution
|
67
|
+
stopped_event.set
|
68
|
+
end
|
69
|
+
|
70
|
+
def ns_running?
|
71
|
+
!stop_event.set?
|
72
|
+
end
|
73
|
+
|
74
|
+
def ns_shuttingdown?
|
75
|
+
!(ns_running? || ns_shutdown?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def ns_shutdown?
|
79
|
+
stopped_event.set?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'concurrent/executor/ruby_thread_pool_executor'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
# @!macro single_thread_executor
|
6
|
+
# @!macro abstract_executor_service_public_api
|
7
|
+
# @!visibility private
|
8
|
+
class RubySingleThreadExecutor < RubyThreadPoolExecutor
|
9
|
+
|
10
|
+
# @!macro single_thread_executor_method_initialize
|
11
|
+
def initialize(opts = {})
|
12
|
+
super(
|
13
|
+
min_threads: 1,
|
14
|
+
max_threads: 1,
|
15
|
+
max_queue: 0,
|
16
|
+
idletime: DEFAULT_THREAD_IDLETIMEOUT,
|
17
|
+
fallback_policy: opts.fetch(:fallback_policy, :discard),
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|