concurrent-ruby 1.0.5 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +115 -0
- data/Gemfile +42 -0
- data/{LICENSE.txt → LICENSE.md} +2 -0
- data/README.md +242 -105
- data/Rakefile +332 -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 +159 -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-ruby.rb +1 -0
- data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
- data/lib/concurrent-ruby/concurrent/array.rb +66 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
- data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
- data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
- data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
- data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
- data/lib/concurrent-ruby/concurrent/map.rb +337 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
- data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
- data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
- data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
- data/lib/concurrent-ruby/concurrent/set.rb +66 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
- data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- metadata +146 -131
- data/lib/concurrent/array.rb +0 -39
- data/lib/concurrent/atomic/atomic_reference.rb +0 -51
- data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
- data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
- data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
- data/lib/concurrent/atomic_reference/jruby.rb +0 -16
- data/lib/concurrent/atomic_reference/rbx.rb +0 -22
- data/lib/concurrent/atomic_reference/ruby.rb +0 -32
- data/lib/concurrent/atomics.rb +0 -53
- data/lib/concurrent/edge.rb +0 -26
- data/lib/concurrent/hash.rb +0 -36
- data/lib/concurrent/lazy_register.rb +0 -81
- data/lib/concurrent/map.rb +0 -240
- data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
- data/lib/concurrent/synchronization/truffle_object.rb +0 -31
- data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
- data/lib/concurrent/utility/at_exit.rb +0 -97
- data/lib/concurrent/utility/native_extension_loader.rb +0 -73
- data/lib/concurrent/version.rb +0 -4
data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb
RENAMED
File without changes
|
File without changes
|
@@ -32,13 +32,13 @@ module Concurrent
|
|
32
32
|
synchronize{ @value = value }
|
33
33
|
end
|
34
34
|
|
35
|
-
# @!macro
|
35
|
+
# @!macro dereferenceable_set_deref_options
|
36
36
|
# Set the options which define the operations #value performs before
|
37
37
|
# returning data to the caller (dereferencing).
|
38
38
|
#
|
39
39
|
# @note Most classes that include this module will call `#set_deref_options`
|
40
|
-
#
|
41
|
-
#
|
40
|
+
# from within the constructor, thus allowing these options to be set at
|
41
|
+
# object creation.
|
42
42
|
#
|
43
43
|
# @param [Hash] opts the options defining dereference behavior.
|
44
44
|
# @option opts [String] :dup_on_deref (false) call `#dup` before returning the data
|
@@ -17,7 +17,12 @@ module Concurrent
|
|
17
17
|
def log(level, progname, message = nil, &block)
|
18
18
|
#NOTE: Cannot require 'concurrent/configuration' above due to circular references.
|
19
19
|
# Assume that the gem has been initialized if we've gotten this far.
|
20
|
-
(@logger
|
20
|
+
logger = if defined?(@logger) && @logger
|
21
|
+
@logger
|
22
|
+
else
|
23
|
+
Concurrent.global_logger
|
24
|
+
end
|
25
|
+
logger.call level, progname, message, &block
|
21
26
|
rescue => error
|
22
27
|
$stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" +
|
23
28
|
"#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}"
|
File without changes
|
@@ -49,7 +49,7 @@ module Concurrent
|
|
49
49
|
# or an AtomicFixum)
|
50
50
|
module Observable
|
51
51
|
|
52
|
-
# @!macro
|
52
|
+
# @!macro observable_add_observer
|
53
53
|
#
|
54
54
|
# Adds an observer to this set. If a block is passed, the observer will be
|
55
55
|
# created by this method and no other params should be passed.
|
@@ -72,8 +72,8 @@ module Concurrent
|
|
72
72
|
self
|
73
73
|
end
|
74
74
|
|
75
|
-
# @!macro
|
76
|
-
#
|
75
|
+
# @!macro observable_delete_observer
|
76
|
+
#
|
77
77
|
# Remove `observer` as an observer on this object so that it will no
|
78
78
|
# longer receive notifications.
|
79
79
|
#
|
@@ -83,17 +83,17 @@ module Concurrent
|
|
83
83
|
observers.delete_observer(observer)
|
84
84
|
end
|
85
85
|
|
86
|
-
# @!macro
|
87
|
-
#
|
86
|
+
# @!macro observable_delete_observers
|
87
|
+
#
|
88
88
|
# Remove all observers associated with this object.
|
89
|
-
#
|
89
|
+
#
|
90
90
|
# @return [Observable] self
|
91
91
|
def delete_observers
|
92
92
|
observers.delete_observers
|
93
93
|
self
|
94
94
|
end
|
95
95
|
|
96
|
-
# @!macro
|
96
|
+
# @!macro observable_count_observers
|
97
97
|
#
|
98
98
|
# Return the number of observers associated with this object.
|
99
99
|
#
|
Binary file
|
@@ -3,12 +3,14 @@ require 'concurrent/delay'
|
|
3
3
|
require 'concurrent/errors'
|
4
4
|
require 'concurrent/atomic/atomic_reference'
|
5
5
|
require 'concurrent/concern/logging'
|
6
|
+
require 'concurrent/concern/deprecation'
|
6
7
|
require 'concurrent/executor/immediate_executor'
|
7
|
-
require 'concurrent/
|
8
|
+
require 'concurrent/executor/cached_thread_pool'
|
8
9
|
require 'concurrent/utility/processor_counter'
|
9
10
|
|
10
11
|
module Concurrent
|
11
12
|
extend Concern::Logging
|
13
|
+
extend Concern::Deprecation
|
12
14
|
|
13
15
|
autoload :Options, 'concurrent/options'
|
14
16
|
autoload :TimerSet, 'concurrent/executor/timer_set'
|
@@ -96,15 +98,15 @@ module Concurrent
|
|
96
98
|
end
|
97
99
|
|
98
100
|
# @!visibility private
|
99
|
-
GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor
|
101
|
+
GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
|
100
102
|
private_constant :GLOBAL_FAST_EXECUTOR
|
101
103
|
|
102
104
|
# @!visibility private
|
103
|
-
GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor
|
105
|
+
GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor }
|
104
106
|
private_constant :GLOBAL_IO_EXECUTOR
|
105
107
|
|
106
108
|
# @!visibility private
|
107
|
-
GLOBAL_TIMER_SET = Delay.new { TimerSet.new
|
109
|
+
GLOBAL_TIMER_SET = Delay.new { TimerSet.new }
|
108
110
|
private_constant :GLOBAL_TIMER_SET
|
109
111
|
|
110
112
|
# @!visibility private
|
@@ -114,7 +116,7 @@ module Concurrent
|
|
114
116
|
# Disables AtExit handlers including pool auto-termination handlers.
|
115
117
|
# When disabled it will be the application programmer's responsibility
|
116
118
|
# to ensure that the handlers are shutdown properly prior to application
|
117
|
-
# exit by calling
|
119
|
+
# exit by calling `AtExit.run` method.
|
118
120
|
#
|
119
121
|
# @note this option should be needed only because of `at_exit` ordering
|
120
122
|
# issues which may arise when running some of the testing frameworks.
|
@@ -124,9 +126,10 @@ module Concurrent
|
|
124
126
|
# @note This method should *never* be called
|
125
127
|
# from within a gem. It should *only* be used from within the main
|
126
128
|
# application and even then it should be used only when necessary.
|
127
|
-
# @see
|
129
|
+
# @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841.
|
130
|
+
#
|
128
131
|
def self.disable_at_exit_handlers!
|
129
|
-
|
132
|
+
deprecated "Method #disable_at_exit_handlers! has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841."
|
130
133
|
end
|
131
134
|
|
132
135
|
# Global thread pool optimized for short, fast *operations*.
|
@@ -170,19 +173,16 @@ module Concurrent
|
|
170
173
|
auto_terminate: opts.fetch(:auto_terminate, true),
|
171
174
|
idletime: 60, # 1 minute
|
172
175
|
max_queue: 0, # unlimited
|
173
|
-
fallback_policy: :abort # shouldn't matter -- 0 max queue
|
176
|
+
fallback_policy: :abort, # shouldn't matter -- 0 max queue
|
177
|
+
name: "fast"
|
174
178
|
)
|
175
179
|
end
|
176
180
|
|
177
181
|
def self.new_io_executor(opts = {})
|
178
|
-
|
179
|
-
min_threads: [2, Concurrent.processor_count].max,
|
180
|
-
max_threads: ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE,
|
181
|
-
# max_threads: 1000,
|
182
|
+
CachedThreadPool.new(
|
182
183
|
auto_terminate: opts.fetch(:auto_terminate, true),
|
183
|
-
|
184
|
-
|
185
|
-
fallback_policy: :abort # shouldn't matter -- 0 max queue
|
184
|
+
fallback_policy: :abort, # shouldn't matter -- 0 max queue
|
185
|
+
name: "io"
|
186
186
|
)
|
187
187
|
end
|
188
188
|
end
|
@@ -18,7 +18,8 @@ module Concurrent
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
21
|
+
# Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
|
22
|
+
# {include:file:docs-source/dataflow.md}
|
22
23
|
#
|
23
24
|
# @param [Future] inputs zero or more `Future` operations that this dataflow depends upon
|
24
25
|
#
|
@@ -32,7 +32,7 @@ module Concurrent
|
|
32
32
|
#
|
33
33
|
# @!macro copy_options
|
34
34
|
#
|
35
|
-
# @!macro
|
35
|
+
# @!macro delay_note_regarding_blocking
|
36
36
|
# @note The default behavior of `Delay` is to block indefinitely when
|
37
37
|
# calling either `value` or `wait`, executing the delayed operation on
|
38
38
|
# the current thread. This makes the `timeout` value completely
|
@@ -81,13 +81,15 @@ module Concurrent
|
|
81
81
|
# this function has been optimized for performance and
|
82
82
|
# should not be modified without running new benchmarks
|
83
83
|
synchronize do
|
84
|
-
execute = @
|
84
|
+
execute = @evaluation_started = true unless @evaluation_started
|
85
85
|
if execute
|
86
86
|
begin
|
87
87
|
set_state(true, @task.call, nil)
|
88
88
|
rescue => ex
|
89
89
|
set_state(false, nil, ex)
|
90
90
|
end
|
91
|
+
elsif incomplete?
|
92
|
+
raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay'
|
91
93
|
end
|
92
94
|
end
|
93
95
|
if @do_nothing_on_deref
|
@@ -144,7 +146,7 @@ module Concurrent
|
|
144
146
|
def reconfigure(&block)
|
145
147
|
synchronize do
|
146
148
|
raise ArgumentError.new('no block given') unless block_given?
|
147
|
-
unless @
|
149
|
+
unless @evaluation_started
|
148
150
|
@task = block
|
149
151
|
true
|
150
152
|
else
|
@@ -160,9 +162,9 @@ module Concurrent
|
|
160
162
|
set_deref_options(opts)
|
161
163
|
@executor = opts[:executor]
|
162
164
|
|
163
|
-
@task
|
164
|
-
@state
|
165
|
-
@
|
165
|
+
@task = block
|
166
|
+
@state = :pending
|
167
|
+
@evaluation_started = false
|
166
168
|
end
|
167
169
|
|
168
170
|
private
|
@@ -173,7 +175,7 @@ module Concurrent
|
|
173
175
|
# should not be modified without running new benchmarks
|
174
176
|
execute = task = nil
|
175
177
|
synchronize do
|
176
|
-
execute = @
|
178
|
+
execute = @evaluation_started = true unless @evaluation_started
|
177
179
|
task = @task
|
178
180
|
end
|
179
181
|
|
File without changes
|
@@ -8,7 +8,7 @@ require 'concurrent/utility/monotonic_time'
|
|
8
8
|
|
9
9
|
module Concurrent
|
10
10
|
|
11
|
-
# @!macro
|
11
|
+
# @!macro exchanger
|
12
12
|
#
|
13
13
|
# A synchronization point at which threads can pair and swap elements within
|
14
14
|
# pairs. Each thread presents some object on entry to the exchange method,
|
@@ -24,9 +24,6 @@ module Concurrent
|
|
24
24
|
# will remain correct.
|
25
25
|
#
|
26
26
|
# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger
|
27
|
-
#
|
28
|
-
# @!macro edge_warning
|
29
|
-
#
|
30
27
|
# @example
|
31
28
|
#
|
32
29
|
# exchanger = Concurrent::Exchanger.new
|
@@ -36,20 +33,19 @@ module Concurrent
|
|
36
33
|
# Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo"
|
37
34
|
# ]
|
38
35
|
# threads.each {|t| t.join(2) }
|
39
|
-
|
36
|
+
|
40
37
|
# @!visibility private
|
41
38
|
class AbstractExchanger < Synchronization::Object
|
42
39
|
|
43
40
|
# @!visibility private
|
44
|
-
CANCEL = Object.new
|
41
|
+
CANCEL = ::Object.new
|
45
42
|
private_constant :CANCEL
|
46
43
|
|
47
|
-
# @!macro [attach] exchanger_method_initialize
|
48
44
|
def initialize
|
49
45
|
super
|
50
46
|
end
|
51
47
|
|
52
|
-
# @!macro
|
48
|
+
# @!macro exchanger_method_do_exchange
|
53
49
|
#
|
54
50
|
# Waits for another thread to arrive at this exchange point (unless the
|
55
51
|
# current thread is interrupted), and then transfers the given object to
|
@@ -61,7 +57,7 @@ module Concurrent
|
|
61
57
|
# @param [Object] value the value to exchange with another thread
|
62
58
|
# @param [Numeric, nil] timeout in seconds, `nil` blocks indefinitely
|
63
59
|
#
|
64
|
-
# @!macro
|
60
|
+
# @!macro exchanger_method_exchange
|
65
61
|
#
|
66
62
|
# In some edge cases when a `timeout` is given a return value of `nil` may be
|
67
63
|
# ambiguous. Specifically, if `nil` is a valid value in the exchange it will
|
@@ -75,8 +71,7 @@ module Concurrent
|
|
75
71
|
end
|
76
72
|
|
77
73
|
# @!macro exchanger_method_do_exchange
|
78
|
-
#
|
79
|
-
# @!macro [attach] exchanger_method_exchange_bang
|
74
|
+
# @!macro exchanger_method_exchange_bang
|
80
75
|
#
|
81
76
|
# On timeout a {Concurrent::TimeoutError} exception will be raised.
|
82
77
|
#
|
@@ -91,8 +86,7 @@ module Concurrent
|
|
91
86
|
end
|
92
87
|
|
93
88
|
# @!macro exchanger_method_do_exchange
|
94
|
-
#
|
95
|
-
# @!macro [attach] exchanger_method_try_exchange
|
89
|
+
# @!macro exchanger_method_try_exchange
|
96
90
|
#
|
97
91
|
# The return value will be a {Concurrent::Maybe} set to `Just` on success or
|
98
92
|
# `Nothing` on timeout.
|
@@ -130,7 +124,6 @@ module Concurrent
|
|
130
124
|
end
|
131
125
|
end
|
132
126
|
|
133
|
-
# @!macro exchanger
|
134
127
|
# @!macro internal_implementation_note
|
135
128
|
# @!visibility private
|
136
129
|
class RubyExchanger < AbstractExchanger
|
@@ -148,8 +141,8 @@ module Concurrent
|
|
148
141
|
|
149
142
|
def initialize(item)
|
150
143
|
super()
|
151
|
-
@Item
|
152
|
-
@Latch
|
144
|
+
@Item = item
|
145
|
+
@Latch = Concurrent::CountDownLatch.new
|
153
146
|
self.value = nil
|
154
147
|
end
|
155
148
|
|
@@ -163,7 +156,6 @@ module Concurrent
|
|
163
156
|
end
|
164
157
|
private_constant :Node
|
165
158
|
|
166
|
-
# @!macro exchanger_method_initialize
|
167
159
|
def initialize
|
168
160
|
super
|
169
161
|
end
|
@@ -218,7 +210,7 @@ module Concurrent
|
|
218
210
|
# node's initial value. It never changes. It's what the fulfiller returns on
|
219
211
|
# success. The occupier's hole is where the fulfiller put its item. It's the
|
220
212
|
# item that the occupier returns on success. The latch is used for synchronization.
|
221
|
-
#
|
213
|
+
# Because a thread may act as either an occupier or fulfiller (or possibly
|
222
214
|
# both in periods of high contention) every thread creates a node when
|
223
215
|
# the exchange method is first called.
|
224
216
|
#
|
@@ -260,8 +252,8 @@ module Concurrent
|
|
260
252
|
# - Wake the sleeping occupier
|
261
253
|
# - Return the occupier's item
|
262
254
|
|
263
|
-
value
|
264
|
-
me
|
255
|
+
value = NULL if value.nil? # The sentinel allows nil to be a valid value
|
256
|
+
me = Node.new(value) # create my node in case I need to occupy
|
265
257
|
end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up
|
266
258
|
|
267
259
|
result = loop do
|
@@ -298,12 +290,10 @@ module Concurrent
|
|
298
290
|
|
299
291
|
if Concurrent.on_jruby?
|
300
292
|
|
301
|
-
# @!macro exchanger
|
302
293
|
# @!macro internal_implementation_note
|
303
294
|
# @!visibility private
|
304
295
|
class JavaExchanger < AbstractExchanger
|
305
296
|
|
306
|
-
# @!macro exchanger_method_initialize
|
307
297
|
def initialize
|
308
298
|
@exchanger = java.util.concurrent.Exchanger.new
|
309
299
|
end
|
@@ -314,11 +304,17 @@ module Concurrent
|
|
314
304
|
#
|
315
305
|
# @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout
|
316
306
|
def do_exchange(value, timeout)
|
307
|
+
result = nil
|
317
308
|
if timeout.nil?
|
318
|
-
|
309
|
+
Synchronization::JRuby.sleep_interruptibly do
|
310
|
+
result = @exchanger.exchange(value)
|
311
|
+
end
|
319
312
|
else
|
320
|
-
|
313
|
+
Synchronization::JRuby.sleep_interruptibly do
|
314
|
+
result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
|
315
|
+
end
|
321
316
|
end
|
317
|
+
result
|
322
318
|
rescue java.util.concurrent.TimeoutException
|
323
319
|
CANCEL
|
324
320
|
end
|
@@ -339,7 +335,7 @@ module Concurrent
|
|
339
335
|
class Exchanger < ExchangerImplementation
|
340
336
|
|
341
337
|
# @!method initialize
|
342
|
-
#
|
338
|
+
# Creates exchanger instance
|
343
339
|
|
344
340
|
# @!method exchange(value, timeout = nil)
|
345
341
|
# @!macro exchanger_method_do_exchange
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'concurrent/errors'
|
2
|
+
require 'concurrent/concern/deprecation'
|
2
3
|
require 'concurrent/executor/executor_service'
|
3
4
|
require 'concurrent/synchronization'
|
4
|
-
require 'concurrent/utility/at_exit'
|
5
5
|
|
6
6
|
module Concurrent
|
7
7
|
|
@@ -9,6 +9,7 @@ module Concurrent
|
|
9
9
|
# @!visibility private
|
10
10
|
class AbstractExecutorService < Synchronization::LockableObject
|
11
11
|
include ExecutorService
|
12
|
+
include Concern::Deprecation
|
12
13
|
|
13
14
|
# The set of possible fallback policies that may be set at thread pool creation.
|
14
15
|
FALLBACK_POLICIES = [:abort, :discard, :caller_runs].freeze
|
@@ -16,10 +17,20 @@ module Concurrent
|
|
16
17
|
# @!macro executor_service_attr_reader_fallback_policy
|
17
18
|
attr_reader :fallback_policy
|
18
19
|
|
20
|
+
attr_reader :name
|
21
|
+
|
19
22
|
# Create a new thread pool.
|
20
|
-
def initialize(
|
23
|
+
def initialize(opts = {}, &block)
|
21
24
|
super(&nil)
|
22
|
-
synchronize
|
25
|
+
synchronize do
|
26
|
+
@auto_terminate = opts.fetch(:auto_terminate, true)
|
27
|
+
@name = opts.fetch(:name) if opts.key?(:name)
|
28
|
+
ns_initialize(opts, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
name ? "#{super[0..-2]} name: #{name}>" : super
|
23
34
|
end
|
24
35
|
|
25
36
|
# @!macro executor_service_method_shutdown
|
@@ -54,12 +65,12 @@ module Concurrent
|
|
54
65
|
|
55
66
|
# @!macro executor_service_method_auto_terminate_question
|
56
67
|
def auto_terminate?
|
57
|
-
synchronize {
|
68
|
+
synchronize { @auto_terminate }
|
58
69
|
end
|
59
70
|
|
60
71
|
# @!macro executor_service_method_auto_terminate_setter
|
61
72
|
def auto_terminate=(value)
|
62
|
-
|
73
|
+
deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized."
|
63
74
|
end
|
64
75
|
|
65
76
|
private
|
@@ -93,7 +104,7 @@ module Concurrent
|
|
93
104
|
raise NotImplementedError
|
94
105
|
end
|
95
106
|
|
96
|
-
# @!macro
|
107
|
+
# @!macro executor_service_method_ns_shutdown_execution
|
97
108
|
#
|
98
109
|
# Callback method called when an orderly shutdown has completed.
|
99
110
|
# The default behavior is to signal all waiting threads.
|
@@ -101,7 +112,7 @@ module Concurrent
|
|
101
112
|
# do nothing
|
102
113
|
end
|
103
114
|
|
104
|
-
# @!macro
|
115
|
+
# @!macro executor_service_method_ns_kill_execution
|
105
116
|
#
|
106
117
|
# Callback method called when the executor has been killed.
|
107
118
|
# The default behavior is to do nothing.
|
@@ -110,25 +121,8 @@ module Concurrent
|
|
110
121
|
end
|
111
122
|
|
112
123
|
def ns_auto_terminate?
|
113
|
-
|
124
|
+
@auto_terminate
|
114
125
|
end
|
115
126
|
|
116
|
-
def ns_auto_terminate=(value)
|
117
|
-
case value
|
118
|
-
when true
|
119
|
-
AtExit.add(self) { terminate_at_exit }
|
120
|
-
@auto_terminate = true
|
121
|
-
when false
|
122
|
-
AtExit.delete(self)
|
123
|
-
@auto_terminate = false
|
124
|
-
else
|
125
|
-
raise ArgumentError
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def terminate_at_exit
|
130
|
-
kill # TODO be gentle first
|
131
|
-
wait_for_termination(10)
|
132
|
-
end
|
133
127
|
end
|
134
128
|
end
|