concurrent-ruby 1.0.5 → 1.1.6
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 +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
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
2
|
-
require 'concurrent/utility/engine'
|
3
|
-
require 'concurrent/atomic_reference/concurrent_update_error'
|
4
|
-
require 'concurrent/atomic_reference/mutex_atomic'
|
5
|
-
|
6
|
-
begin
|
7
|
-
# force fallback impl with FORCE_ATOMIC_FALLBACK=1
|
8
|
-
if /[^0fF]/ =~ ENV['FORCE_ATOMIC_FALLBACK']
|
9
|
-
ruby_engine = 'mutex_atomic'
|
10
|
-
else
|
11
|
-
ruby_engine = Concurrent.ruby_engine
|
12
|
-
end
|
13
|
-
|
14
|
-
require "concurrent/atomic_reference/#{ruby_engine}"
|
15
|
-
rescue LoadError
|
16
|
-
#warn 'Compiled extensions not installed, pure Ruby Atomic will be used.'
|
17
|
-
end
|
18
|
-
|
19
|
-
if defined? Concurrent::JavaAtomicReference
|
20
|
-
|
21
|
-
# @!macro atomic_reference
|
22
|
-
class Concurrent::AtomicReference < Concurrent::JavaAtomicReference
|
23
|
-
end
|
24
|
-
|
25
|
-
elsif defined? Concurrent::RbxAtomicReference
|
26
|
-
|
27
|
-
# @!macro atomic_reference
|
28
|
-
class Concurrent::AtomicReference < Concurrent::RbxAtomicReference
|
29
|
-
end
|
30
|
-
|
31
|
-
elsif defined? Concurrent::CAtomicReference
|
32
|
-
|
33
|
-
# @!macro atomic_reference
|
34
|
-
class Concurrent::AtomicReference < Concurrent::CAtomicReference
|
35
|
-
end
|
36
|
-
|
37
|
-
else
|
38
|
-
|
39
|
-
# @!macro atomic_reference
|
40
|
-
class Concurrent::AtomicReference < Concurrent::MutexAtomicReference
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class Concurrent::AtomicReference
|
45
|
-
# @return [String] Short string representation.
|
46
|
-
def to_s
|
47
|
-
format '<#%s:0x%x value:%s>', self.class, object_id << 1, get
|
48
|
-
end
|
49
|
-
|
50
|
-
alias_method :inspect, :to_s
|
51
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'concurrent/atomic_reference/concurrent_update_error'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
# Define update methods that use direct paths
|
6
|
-
#
|
7
|
-
# @!visibility private
|
8
|
-
# @!macro internal_implementation_note
|
9
|
-
module AtomicDirectUpdate
|
10
|
-
|
11
|
-
# @!macro [attach] atomic_reference_method_update
|
12
|
-
#
|
13
|
-
# Pass the current value to the given block, replacing it
|
14
|
-
# with the block's result. May retry if the value changes
|
15
|
-
# during the block's execution.
|
16
|
-
#
|
17
|
-
# @yield [Object] Calculate a new value for the atomic reference using
|
18
|
-
# given (old) value
|
19
|
-
# @yieldparam [Object] old_value the starting value of the atomic reference
|
20
|
-
#
|
21
|
-
# @return [Object] the new value
|
22
|
-
def update
|
23
|
-
true until compare_and_set(old_value = get, new_value = yield(old_value))
|
24
|
-
new_value
|
25
|
-
end
|
26
|
-
|
27
|
-
# @!macro [attach] atomic_reference_method_try_update
|
28
|
-
#
|
29
|
-
# Pass the current value to the given block, replacing it
|
30
|
-
# with the block's result. Return nil if the update fails.
|
31
|
-
#
|
32
|
-
# @yield [Object] Calculate a new value for the atomic reference using
|
33
|
-
# given (old) value
|
34
|
-
# @yieldparam [Object] old_value the starting value of the atomic reference
|
35
|
-
#
|
36
|
-
# @note This method was altered to avoid raising an exception by default.
|
37
|
-
# Instead, this method now returns `nil` in case of failure. For more info,
|
38
|
-
# please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
|
39
|
-
#
|
40
|
-
# @return [Object] the new value, or nil if update failed
|
41
|
-
def try_update
|
42
|
-
old_value = get
|
43
|
-
new_value = yield old_value
|
44
|
-
|
45
|
-
return unless compare_and_set old_value, new_value
|
46
|
-
|
47
|
-
new_value
|
48
|
-
end
|
49
|
-
|
50
|
-
# @!macro [attach] atomic_reference_method_try_update!
|
51
|
-
#
|
52
|
-
# Pass the current value to the given block, replacing it
|
53
|
-
# with the block's result. Raise an exception if the update
|
54
|
-
# fails.
|
55
|
-
#
|
56
|
-
# @yield [Object] Calculate a new value for the atomic reference using
|
57
|
-
# given (old) value
|
58
|
-
# @yieldparam [Object] old_value the starting value of the atomic reference
|
59
|
-
#
|
60
|
-
# @note This behavior mimics the behavior of the original
|
61
|
-
# `AtomicReference#try_update` API. The reason this was changed was to
|
62
|
-
# avoid raising exceptions (which are inherently slow) by default. For more
|
63
|
-
# info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336
|
64
|
-
#
|
65
|
-
# @return [Object] the new value
|
66
|
-
#
|
67
|
-
# @raise [Concurrent::ConcurrentUpdateError] if the update fails
|
68
|
-
def try_update!
|
69
|
-
old_value = get
|
70
|
-
new_value = yield old_value
|
71
|
-
unless compare_and_set(old_value, new_value)
|
72
|
-
if $VERBOSE
|
73
|
-
raise ConcurrentUpdateError, "Update failed"
|
74
|
-
else
|
75
|
-
raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
|
76
|
-
end
|
77
|
-
end
|
78
|
-
new_value
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
2
|
-
|
3
|
-
if defined?(Concurrent::JavaAtomicReference)
|
4
|
-
require 'concurrent/atomic_reference/direct_update'
|
5
|
-
|
6
|
-
module Concurrent
|
7
|
-
|
8
|
-
# @!macro atomic_reference
|
9
|
-
#
|
10
|
-
# @!visibility private
|
11
|
-
# @!macro internal_implementation_note
|
12
|
-
class JavaAtomicReference
|
13
|
-
include Concurrent::AtomicDirectUpdate
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'concurrent/atomic_reference/direct_update'
|
2
|
-
require 'concurrent/atomic_reference/numeric_cas_wrapper'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
# @!macro atomic_reference
|
7
|
-
#
|
8
|
-
# @note Extends `Rubinius::AtomicReference` version adding aliases
|
9
|
-
# and numeric logic.
|
10
|
-
#
|
11
|
-
# @!visibility private
|
12
|
-
# @!macro internal_implementation_note
|
13
|
-
class RbxAtomicReference < Rubinius::AtomicReference
|
14
|
-
alias _compare_and_set compare_and_set
|
15
|
-
include Concurrent::AtomicDirectUpdate
|
16
|
-
include Concurrent::AtomicNumericCompareAndSetWrapper
|
17
|
-
|
18
|
-
alias_method :value, :get
|
19
|
-
alias_method :value=, :set
|
20
|
-
alias_method :swap, :get_and_set
|
21
|
-
end
|
22
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
if defined? Concurrent::CAtomicReference
|
2
|
-
require 'concurrent/synchronization'
|
3
|
-
require 'concurrent/atomic_reference/direct_update'
|
4
|
-
require 'concurrent/atomic_reference/numeric_cas_wrapper'
|
5
|
-
|
6
|
-
module Concurrent
|
7
|
-
|
8
|
-
# @!macro atomic_reference
|
9
|
-
#
|
10
|
-
# @!visibility private
|
11
|
-
# @!macro internal_implementation_note
|
12
|
-
class CAtomicReference
|
13
|
-
include Concurrent::AtomicDirectUpdate
|
14
|
-
include Concurrent::AtomicNumericCompareAndSetWrapper
|
15
|
-
|
16
|
-
# @!method initialize
|
17
|
-
# @!macro atomic_reference_method_initialize
|
18
|
-
|
19
|
-
# @!method get
|
20
|
-
# @!macro atomic_reference_method_get
|
21
|
-
|
22
|
-
# @!method set
|
23
|
-
# @!macro atomic_reference_method_set
|
24
|
-
|
25
|
-
# @!method get_and_set
|
26
|
-
# @!macro atomic_reference_method_get_and_set
|
27
|
-
|
28
|
-
# @!method _compare_and_set
|
29
|
-
# @!macro atomic_reference_method_compare_and_set
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/lib/concurrent/atomics.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# @!macro [new] atomic_reference
|
2
|
-
#
|
3
|
-
# An object reference that may be updated atomically. All read and write
|
4
|
-
# operations have java volatile semantic.
|
5
|
-
#
|
6
|
-
# @!macro thread_safe_variable_comparison
|
7
|
-
#
|
8
|
-
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
|
9
|
-
# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html
|
10
|
-
#
|
11
|
-
# @!method initialize
|
12
|
-
# @!macro [new] atomic_reference_method_initialize
|
13
|
-
# @param [Object] value The initial value.
|
14
|
-
#
|
15
|
-
# @!method get
|
16
|
-
# @!macro [new] atomic_reference_method_get
|
17
|
-
# Gets the current value.
|
18
|
-
# @return [Object] the current value
|
19
|
-
#
|
20
|
-
# @!method set
|
21
|
-
# @!macro [new] atomic_reference_method_set
|
22
|
-
# Sets to the given value.
|
23
|
-
# @param [Object] new_value the new value
|
24
|
-
# @return [Object] the new value
|
25
|
-
#
|
26
|
-
# @!method get_and_set
|
27
|
-
# @!macro [new] atomic_reference_method_get_and_set
|
28
|
-
# Atomically sets to the given value and returns the old value.
|
29
|
-
# @param [Object] new_value the new value
|
30
|
-
# @return [Object] the old value
|
31
|
-
#
|
32
|
-
# @!method compare_and_set
|
33
|
-
# @!macro [new] atomic_reference_method_compare_and_set
|
34
|
-
#
|
35
|
-
# Atomically sets the value to the given updated value if
|
36
|
-
# the current value == the expected value.
|
37
|
-
#
|
38
|
-
# @param [Object] old_value the expected value
|
39
|
-
# @param [Object] new_value the new value
|
40
|
-
#
|
41
|
-
# @return [Boolean] `true` if successful. A `false` return indicates
|
42
|
-
# that the actual value was not equal to the expected value.
|
43
|
-
|
44
|
-
require 'concurrent/atomic/atomic_reference'
|
45
|
-
require 'concurrent/atomic/atomic_boolean'
|
46
|
-
require 'concurrent/atomic/atomic_fixnum'
|
47
|
-
require 'concurrent/atomic/cyclic_barrier'
|
48
|
-
require 'concurrent/atomic/count_down_latch'
|
49
|
-
require 'concurrent/atomic/event'
|
50
|
-
require 'concurrent/atomic/read_write_lock'
|
51
|
-
require 'concurrent/atomic/reentrant_read_write_lock'
|
52
|
-
require 'concurrent/atomic/semaphore'
|
53
|
-
require 'concurrent/atomic/thread_local_var'
|
data/lib/concurrent/edge.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Concurrent
|
2
|
-
|
3
|
-
# A submodule for unstable, highly experimental features that are likely to
|
4
|
-
# change often and which may never become part of the core gem. Also for
|
5
|
-
# new, experimental version of abstractions already in the core gem.
|
6
|
-
#
|
7
|
-
# Most new features should start in this module, clearly indicating the
|
8
|
-
# experimental and unstable nature of the feature. Once a feature becomes
|
9
|
-
# more stable and is a candidate for inclusion in the core gem it should
|
10
|
-
# be moved up to the `Concurrent` module, where it would reside once merged
|
11
|
-
# into the core gem.
|
12
|
-
#
|
13
|
-
# The only exception to this is for features which *replace* features from
|
14
|
-
# the core gem in ways that are breaking and not backward compatible. These
|
15
|
-
# features should remain in this module until merged into the core gem. This
|
16
|
-
# will prevent namespace collisions.
|
17
|
-
#
|
18
|
-
# @!macro [attach] edge_warning
|
19
|
-
# @api Edge
|
20
|
-
# @note **Edge Feature:** Edge features are under active development and may change frequently. They are expected not to
|
21
|
-
# keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|
22
|
-
# be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move
|
23
|
-
# to `concurrent-ruby` when final.
|
24
|
-
module Edge
|
25
|
-
end
|
26
|
-
end
|
data/lib/concurrent/hash.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'concurrent/utility/engine'
|
2
|
-
require 'concurrent/thread_safe/util'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
if Concurrent.on_cruby?
|
6
|
-
|
7
|
-
# @!macro [attach] concurrent_hash
|
8
|
-
#
|
9
|
-
# A thread-safe subclass of Hash. This version locks against the object
|
10
|
-
# itself for every method call, ensuring only one thread can be reading
|
11
|
-
# or writing at a time. This includes iteration methods like `#each`,
|
12
|
-
# which takes the lock repeatedly when reading an item.
|
13
|
-
#
|
14
|
-
# @see http://ruby-doc.org/core-2.2.0/Hash.html Ruby standard library `Hash`
|
15
|
-
class Hash < ::Hash;
|
16
|
-
end
|
17
|
-
|
18
|
-
elsif Concurrent.on_jruby?
|
19
|
-
require 'jruby/synchronized'
|
20
|
-
|
21
|
-
# @!macro concurrent_hash
|
22
|
-
class Hash < ::Hash
|
23
|
-
include JRuby::Synchronized
|
24
|
-
end
|
25
|
-
|
26
|
-
elsif Concurrent.on_rbx? || Concurrent.on_truffle?
|
27
|
-
require 'monitor'
|
28
|
-
require 'concurrent/thread_safe/util/array_hash_rbx'
|
29
|
-
|
30
|
-
# @!macro concurrent_hash
|
31
|
-
class Hash < ::Hash
|
32
|
-
end
|
33
|
-
|
34
|
-
ThreadSafe::Util.make_synchronized_on_rbx Hash
|
35
|
-
end
|
36
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'concurrent/atomic/atomic_reference'
|
2
|
-
require 'concurrent/delay'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
# Hash-like collection that store lazys evaluated values.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# register = Concurrent::LazyRegister.new
|
10
|
-
# #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
|
11
|
-
# register[:key]
|
12
|
-
# #=> nil
|
13
|
-
# register.add(:key) { Concurrent::Actor.spawn!(Actor::AdHoc, :ping) { -> message { message } } }
|
14
|
-
# #=> #<Concurrent::LazyRegister:0x007fd7ecd5e230 @Data=#<Concurrent::AtomicReference:0x007fd7ecd5e1e0>>
|
15
|
-
# register[:key]
|
16
|
-
# #=> #<Concurrent::Actor::Reference /ping (Concurrent::Actor::AdHoc)>
|
17
|
-
#
|
18
|
-
# @!macro edge_warning
|
19
|
-
class LazyRegister < Synchronization::Object
|
20
|
-
|
21
|
-
private(*attr_atomic(:data))
|
22
|
-
|
23
|
-
def initialize
|
24
|
-
super
|
25
|
-
self.data = {}
|
26
|
-
end
|
27
|
-
|
28
|
-
# Element reference. Retrieves the value object corresponding to the
|
29
|
-
# key object. Returns nil if the key is not found. Raises an exception
|
30
|
-
# if the stored item raised an exception when the block was evaluated.
|
31
|
-
#
|
32
|
-
# @param [Object] key
|
33
|
-
# @return [Object] value stored for the key or nil if the key is not found
|
34
|
-
#
|
35
|
-
# @raise Exception when the initialization block fails
|
36
|
-
def [](key)
|
37
|
-
delay = data[key]
|
38
|
-
delay ? delay.value! : nil
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns true if the given key is present.
|
42
|
-
#
|
43
|
-
# @param [Object] key
|
44
|
-
# @return [true, false] if the key is registered
|
45
|
-
def registered?(key)
|
46
|
-
data.key?(key)
|
47
|
-
end
|
48
|
-
|
49
|
-
alias_method :key?, :registered?
|
50
|
-
alias_method :has_key?, :registered?
|
51
|
-
|
52
|
-
# Element assignment. Associates the value given by value with the
|
53
|
-
# key given by key.
|
54
|
-
#
|
55
|
-
# @param [Object] key
|
56
|
-
# @yield the object to store under the key
|
57
|
-
#
|
58
|
-
# @return [LazyRegister] self
|
59
|
-
def register(key, &block)
|
60
|
-
delay = Delay.new(executor: :immediate, &block)
|
61
|
-
update_data { |h| h.merge(key => delay) }
|
62
|
-
self
|
63
|
-
end
|
64
|
-
|
65
|
-
alias_method :add, :register
|
66
|
-
alias_method :store, :register
|
67
|
-
|
68
|
-
# Un-registers the object under key, realized or not.
|
69
|
-
#
|
70
|
-
# @param [Object] key
|
71
|
-
#
|
72
|
-
# @return [LazyRegister] self
|
73
|
-
def unregister(key)
|
74
|
-
update_data { |h| h.dup.tap { |j| j.delete(key) } }
|
75
|
-
self
|
76
|
-
end
|
77
|
-
|
78
|
-
alias_method :remove, :unregister
|
79
|
-
alias_method :delete, :unregister
|
80
|
-
end
|
81
|
-
end
|
data/lib/concurrent/map.rb
DELETED
@@ -1,240 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
require 'concurrent/constants'
|
3
|
-
require 'concurrent/synchronization'
|
4
|
-
|
5
|
-
module Concurrent
|
6
|
-
# @!visibility private
|
7
|
-
module Collection
|
8
|
-
|
9
|
-
# @!visibility private
|
10
|
-
MapImplementation = if Concurrent.java_extensions_loaded?
|
11
|
-
# noinspection RubyResolve
|
12
|
-
JRubyMapBackend
|
13
|
-
elsif defined?(RUBY_ENGINE)
|
14
|
-
case RUBY_ENGINE
|
15
|
-
when 'ruby'
|
16
|
-
require 'concurrent/collection/map/mri_map_backend'
|
17
|
-
MriMapBackend
|
18
|
-
when 'rbx'
|
19
|
-
require 'concurrent/collection/map/atomic_reference_map_backend'
|
20
|
-
AtomicReferenceMapBackend
|
21
|
-
when 'jruby+truffle'
|
22
|
-
require 'concurrent/collection/map/atomic_reference_map_backend'
|
23
|
-
AtomicReferenceMapBackend
|
24
|
-
else
|
25
|
-
warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' if $VERBOSE
|
26
|
-
require 'concurrent/collection/map/synchronized_map_backend'
|
27
|
-
SynchronizedMapBackend
|
28
|
-
end
|
29
|
-
else
|
30
|
-
MriMapBackend
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# `Concurrent::Map` is a hash-like object and should have much better performance
|
35
|
-
# characteristics, especially under high concurrency, than `Concurrent::Hash`.
|
36
|
-
# However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash`
|
37
|
-
# -- for instance, it does not necessarily retain ordering by insertion time as `Hash`
|
38
|
-
# does. For most uses it should do fine though, and we recommend you consider
|
39
|
-
# `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs.
|
40
|
-
#
|
41
|
-
# > require 'concurrent'
|
42
|
-
# >
|
43
|
-
# > map = Concurrent::Map.new
|
44
|
-
class Map < Collection::MapImplementation
|
45
|
-
|
46
|
-
# @!macro [new] map_method_is_atomic
|
47
|
-
# This method is atomic. Atomic methods of `Map` which accept a block
|
48
|
-
# do not allow the `self` instance to be used within the block. Doing
|
49
|
-
# so will cause a deadlock.
|
50
|
-
|
51
|
-
# @!method put_if_absent
|
52
|
-
# @!macro map_method_is_atomic
|
53
|
-
|
54
|
-
# @!method compute_if_absent
|
55
|
-
# @!macro map_method_is_atomic
|
56
|
-
|
57
|
-
# @!method compute_if_present
|
58
|
-
# @!macro map_method_is_atomic
|
59
|
-
|
60
|
-
# @!method compute
|
61
|
-
# @!macro map_method_is_atomic
|
62
|
-
|
63
|
-
# @!method merge_pair
|
64
|
-
# @!macro map_method_is_atomic
|
65
|
-
|
66
|
-
# @!method replace_pair
|
67
|
-
# @!macro map_method_is_atomic
|
68
|
-
|
69
|
-
# @!method replace_if_exists
|
70
|
-
# @!macro map_method_is_atomic
|
71
|
-
|
72
|
-
# @!method get_and_set
|
73
|
-
# @!macro map_method_is_atomic
|
74
|
-
|
75
|
-
# @!method delete
|
76
|
-
# @!macro map_method_is_atomic
|
77
|
-
|
78
|
-
# @!method delete_pair
|
79
|
-
# @!macro map_method_is_atomic
|
80
|
-
|
81
|
-
def initialize(options = nil, &block)
|
82
|
-
if options.kind_of?(::Hash)
|
83
|
-
validate_options_hash!(options)
|
84
|
-
else
|
85
|
-
options = nil
|
86
|
-
end
|
87
|
-
|
88
|
-
super(options)
|
89
|
-
@default_proc = block
|
90
|
-
end
|
91
|
-
|
92
|
-
def [](key)
|
93
|
-
if value = super # non-falsy value is an existing mapping, return it right away
|
94
|
-
value
|
95
|
-
# re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
|
96
|
-
# a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
|
97
|
-
# would be returned)
|
98
|
-
# note: nil == value check is not technically necessary
|
99
|
-
elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
|
100
|
-
@default_proc.call(self, key)
|
101
|
-
else
|
102
|
-
value
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
alias_method :get, :[]
|
107
|
-
alias_method :put, :[]=
|
108
|
-
|
109
|
-
# @!macro [attach] map_method_not_atomic
|
110
|
-
# The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended
|
111
|
-
# to be use as a concurrency primitive with strong happens-before
|
112
|
-
# guarantees. It is not intended to be used as a high-level abstraction
|
113
|
-
# supporting complex operations. All read and write operations are
|
114
|
-
# thread safe, but no guarantees are made regarding race conditions
|
115
|
-
# between the fetch operation and yielding to the block. Additionally,
|
116
|
-
# this method does not support recursion. This is due to internal
|
117
|
-
# constraints that are very unlikely to change in the near future.
|
118
|
-
def fetch(key, default_value = NULL)
|
119
|
-
if NULL != (value = get_or_default(key, NULL))
|
120
|
-
value
|
121
|
-
elsif block_given?
|
122
|
-
yield key
|
123
|
-
elsif NULL != default_value
|
124
|
-
default_value
|
125
|
-
else
|
126
|
-
raise_fetch_no_key
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# @!macro map_method_not_atomic
|
131
|
-
def fetch_or_store(key, default_value = NULL)
|
132
|
-
fetch(key) do
|
133
|
-
put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# @!macro map_method_is_atomic
|
138
|
-
def put_if_absent(key, value)
|
139
|
-
computed = false
|
140
|
-
result = compute_if_absent(key) do
|
141
|
-
computed = true
|
142
|
-
value
|
143
|
-
end
|
144
|
-
computed ? nil : result
|
145
|
-
end unless method_defined?(:put_if_absent)
|
146
|
-
|
147
|
-
def value?(value)
|
148
|
-
each_value do |v|
|
149
|
-
return true if value.equal?(v)
|
150
|
-
end
|
151
|
-
false
|
152
|
-
end
|
153
|
-
|
154
|
-
def keys
|
155
|
-
arr = []
|
156
|
-
each_pair {|k, v| arr << k}
|
157
|
-
arr
|
158
|
-
end unless method_defined?(:keys)
|
159
|
-
|
160
|
-
def values
|
161
|
-
arr = []
|
162
|
-
each_pair {|k, v| arr << v}
|
163
|
-
arr
|
164
|
-
end unless method_defined?(:values)
|
165
|
-
|
166
|
-
def each_key
|
167
|
-
each_pair {|k, v| yield k}
|
168
|
-
end unless method_defined?(:each_key)
|
169
|
-
|
170
|
-
def each_value
|
171
|
-
each_pair {|k, v| yield v}
|
172
|
-
end unless method_defined?(:each_value)
|
173
|
-
|
174
|
-
alias_method :each, :each_pair unless method_defined?(:each)
|
175
|
-
|
176
|
-
def key(value)
|
177
|
-
each_pair {|k, v| return k if v == value}
|
178
|
-
nil
|
179
|
-
end unless method_defined?(:key)
|
180
|
-
alias_method :index, :key if RUBY_VERSION < '1.9'
|
181
|
-
|
182
|
-
def empty?
|
183
|
-
each_pair {|k, v| return false}
|
184
|
-
true
|
185
|
-
end unless method_defined?(:empty?)
|
186
|
-
|
187
|
-
def size
|
188
|
-
count = 0
|
189
|
-
each_pair {|k, v| count += 1}
|
190
|
-
count
|
191
|
-
end unless method_defined?(:size)
|
192
|
-
|
193
|
-
def marshal_dump
|
194
|
-
raise TypeError, "can't dump hash with default proc" if @default_proc
|
195
|
-
h = {}
|
196
|
-
each_pair {|k, v| h[k] = v}
|
197
|
-
h
|
198
|
-
end
|
199
|
-
|
200
|
-
def marshal_load(hash)
|
201
|
-
initialize
|
202
|
-
populate_from(hash)
|
203
|
-
end
|
204
|
-
|
205
|
-
undef :freeze
|
206
|
-
|
207
|
-
# @!visibility private
|
208
|
-
DEFAULT_OBJ_ID_STR_WIDTH = 0.size == 4 ? 7 : 14 # we want to look "native", 7 for 32-bit, 14 for 64-bit
|
209
|
-
# override default #inspect() method: firstly, we don't want to be spilling our guts (i-vars), secondly, MRI backend's
|
210
|
-
# #inspect() call on its @backend i-var will bump @backend's iter level while possibly yielding GVL
|
211
|
-
def inspect
|
212
|
-
id_str = (object_id << 1).to_s(16).rjust(DEFAULT_OBJ_ID_STR_WIDTH, '0')
|
213
|
-
"#<#{self.class.name}:0x#{id_str} entries=#{size} default_proc=#{@default_proc.inspect}>"
|
214
|
-
end
|
215
|
-
|
216
|
-
private
|
217
|
-
def raise_fetch_no_key
|
218
|
-
raise KeyError, 'key not found'
|
219
|
-
end
|
220
|
-
|
221
|
-
def initialize_copy(other)
|
222
|
-
super
|
223
|
-
populate_from(other)
|
224
|
-
end
|
225
|
-
|
226
|
-
def populate_from(hash)
|
227
|
-
hash.each_pair {|k, v| self[k] = v}
|
228
|
-
self
|
229
|
-
end
|
230
|
-
|
231
|
-
def validate_options_hash!(options)
|
232
|
-
if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Integer) || initial_capacity < 0)
|
233
|
-
raise ArgumentError, ":initial_capacity must be a positive Integer"
|
234
|
-
end
|
235
|
-
if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1)
|
236
|
-
raise ArgumentError, ":load_factor must be a number between 0 and 1"
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|