concurrent-ruby 1.1.10 → 1.2.0
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 +4 -4
- data/CHANGELOG.md +11 -1
- data/Gemfile +0 -1
- data/README.md +21 -20
- data/Rakefile +46 -57
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
- data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
- data/lib/concurrent-ruby/concurrent/array.rb +0 -10
- data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
- data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +81 -151
- data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
- data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/locals.rb +188 -0
- data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
- data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
- data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
- data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +5 -3
- data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
- data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
- data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
- data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
- data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
- data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
- data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
- data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
- data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
- data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +2 -2
- data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
- data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
- data/lib/concurrent-ruby/concurrent/hash.rb +0 -9
- data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
- data/lib/concurrent-ruby/concurrent/map.rb +9 -8
- data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
- data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
- data/lib/concurrent-ruby/concurrent/promise.rb +1 -1
- data/lib/concurrent-ruby/concurrent/promises.rb +7 -6
- data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
- data/lib/concurrent-ruby/concurrent/scheduled_task.rb +1 -1
- data/lib/concurrent-ruby/concurrent/set.rb +0 -10
- data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
- data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
- data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
- data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
- data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
- data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
- data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
- data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
- data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +2 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
- data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
- data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
- data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
- data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
- data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +34 -54
- data/lib/concurrent-ruby/concurrent/version.rb +1 -1
- metadata +13 -15
- data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
- data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
- data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
- data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
- data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
- data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
- data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
@@ -1,5 +1,8 @@
|
|
1
|
-
require 'concurrent/
|
1
|
+
require 'concurrent/atomic/atomic_boolean'
|
2
|
+
require 'concurrent/atomic/atomic_fixnum'
|
3
|
+
require 'concurrent/atomic/event'
|
2
4
|
require 'concurrent/executor/executor_service'
|
5
|
+
require 'concurrent/executor/ruby_executor_service'
|
3
6
|
|
4
7
|
module Concurrent
|
5
8
|
|
@@ -28,15 +28,6 @@ module Concurrent
|
|
28
28
|
end
|
29
29
|
JRubyHash
|
30
30
|
|
31
|
-
when Concurrent.on_rbx?
|
32
|
-
require 'monitor'
|
33
|
-
require 'concurrent/thread_safe/util/data_structures'
|
34
|
-
|
35
|
-
class RbxHash < ::Hash
|
36
|
-
end
|
37
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxHash
|
38
|
-
RbxHash
|
39
|
-
|
40
31
|
when Concurrent.on_truffleruby?
|
41
32
|
require 'concurrent/thread_safe/util/data_structures'
|
42
33
|
|
@@ -3,7 +3,8 @@ require 'concurrent/errors'
|
|
3
3
|
require 'concurrent/collection/copy_on_write_observer_set'
|
4
4
|
require 'concurrent/concern/obligation'
|
5
5
|
require 'concurrent/concern/observable'
|
6
|
-
require 'concurrent/
|
6
|
+
require 'concurrent/executor/safe_task_executor'
|
7
|
+
require 'concurrent/synchronization/lockable_object'
|
7
8
|
|
8
9
|
module Concurrent
|
9
10
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'concurrent/constants'
|
3
|
-
require 'concurrent/synchronization'
|
4
3
|
require 'concurrent/utility/engine'
|
5
4
|
|
6
5
|
module Concurrent
|
@@ -10,17 +9,20 @@ module Concurrent
|
|
10
9
|
# @!visibility private
|
11
10
|
MapImplementation = case
|
12
11
|
when Concurrent.on_jruby?
|
12
|
+
require 'concurrent/utility/native_extension_loader'
|
13
13
|
# noinspection RubyResolve
|
14
14
|
JRubyMapBackend
|
15
15
|
when Concurrent.on_cruby?
|
16
16
|
require 'concurrent/collection/map/mri_map_backend'
|
17
17
|
MriMapBackend
|
18
|
-
when Concurrent.on_truffleruby?
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
when Concurrent.on_truffleruby?
|
19
|
+
if defined?(::TruffleRuby::ConcurrentMap)
|
20
|
+
require 'concurrent/collection/map/truffleruby_map_backend'
|
21
|
+
TruffleRubyMapBackend
|
22
|
+
else
|
23
|
+
require 'concurrent/collection/map/atomic_reference_map_backend'
|
24
|
+
AtomicReferenceMapBackend
|
25
|
+
end
|
24
26
|
else
|
25
27
|
warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation'
|
26
28
|
require 'concurrent/collection/map/synchronized_map_backend'
|
@@ -197,7 +199,6 @@ module Concurrent
|
|
197
199
|
# @yieldparam key [Object]
|
198
200
|
# @yieldreturn [Object] default value
|
199
201
|
# @return [Object] the value or default value
|
200
|
-
# @!macro map.atomic_method_with_block
|
201
202
|
def fetch_or_store(key, default_value = NULL)
|
202
203
|
fetch(key) do
|
203
204
|
put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
|
@@ -1,7 +1,8 @@
|
|
1
|
-
require 'concurrent/synchronization'
|
1
|
+
require 'concurrent/synchronization/object'
|
2
2
|
require 'concurrent/atomic/atomic_boolean'
|
3
3
|
require 'concurrent/atomic/atomic_fixnum'
|
4
4
|
require 'concurrent/collection/lock_free_stack'
|
5
|
+
require 'concurrent/configuration'
|
5
6
|
require 'concurrent/errors'
|
6
7
|
require 'concurrent/re_include'
|
7
8
|
|
@@ -313,7 +314,7 @@ module Concurrent
|
|
313
314
|
end
|
314
315
|
|
315
316
|
# @!macro promises.shortcut.on
|
316
|
-
# @return [
|
317
|
+
# @return [Event]
|
317
318
|
def any_event(*futures_and_or_events)
|
318
319
|
any_event_on default_executor, *futures_and_or_events
|
319
320
|
end
|
@@ -892,7 +893,7 @@ module Concurrent
|
|
892
893
|
private
|
893
894
|
|
894
895
|
def rejected_resolution(raise_on_reassign, state)
|
895
|
-
Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
|
+
raise Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign
|
896
897
|
return false
|
897
898
|
end
|
898
899
|
|
@@ -1298,7 +1299,7 @@ module Concurrent
|
|
1298
1299
|
|
1299
1300
|
# @!macro promise.param.raise_on_reassign
|
1300
1301
|
# @param [Boolean] raise_on_reassign should method raise exception if already resolved
|
1301
|
-
# @return [self, false] false is
|
1302
|
+
# @return [self, false] false is returned when raise_on_reassign is false and the receiver
|
1302
1303
|
# is already resolved.
|
1303
1304
|
#
|
1304
1305
|
|
@@ -2074,8 +2075,8 @@ module Concurrent
|
|
2074
2075
|
|
2075
2076
|
private
|
2076
2077
|
|
2077
|
-
def resolvable?(countdown,
|
2078
|
-
|
2078
|
+
def resolvable?(countdown, event_or_future, index)
|
2079
|
+
(event_or_future.is_a?(Event) ? event_or_future.resolved? : event_or_future.fulfilled?) ||
|
2079
2080
|
# inlined super from BlockedPromise
|
2080
2081
|
countdown.zero?
|
2081
2082
|
end
|
@@ -42,16 +42,6 @@ module Concurrent
|
|
42
42
|
|
43
43
|
JRubySet
|
44
44
|
|
45
|
-
when Concurrent.on_rbx?
|
46
|
-
require 'monitor'
|
47
|
-
require 'concurrent/thread_safe/util/data_structures'
|
48
|
-
|
49
|
-
class RbxSet < ::Set
|
50
|
-
end
|
51
|
-
|
52
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxSet
|
53
|
-
RbxSet
|
54
|
-
|
55
45
|
when Concurrent.on_truffleruby?
|
56
46
|
require 'concurrent/thread_safe/util/data_structures'
|
57
47
|
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
require 'concurrent/utility/monotonic_time'
|
3
|
+
require 'concurrent/synchronization/object'
|
4
|
+
|
1
5
|
module Concurrent
|
2
6
|
module Synchronization
|
3
7
|
|
@@ -34,7 +38,7 @@ module Concurrent
|
|
34
38
|
if timeout
|
35
39
|
wait_until = Concurrent.monotonic_time + timeout
|
36
40
|
loop do
|
37
|
-
now
|
41
|
+
now = Concurrent.monotonic_time
|
38
42
|
condition_result = condition.call
|
39
43
|
return condition_result if now >= wait_until || condition_result
|
40
44
|
ns_wait wait_until - now
|
@@ -4,10 +4,8 @@ module Concurrent
|
|
4
4
|
# @!visibility private
|
5
5
|
# @!macro internal_implementation_note
|
6
6
|
class AbstractObject
|
7
|
-
|
8
|
-
# @abstract has to be implemented based on Ruby runtime
|
9
7
|
def initialize
|
10
|
-
|
8
|
+
# nothing to do
|
11
9
|
end
|
12
10
|
|
13
11
|
# @!visibility private
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
module Synchronization
|
5
|
+
case
|
6
|
+
when Concurrent.on_cruby?
|
7
|
+
def self.full_memory_barrier
|
8
|
+
# relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
|
9
|
+
# https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
|
10
|
+
end
|
11
|
+
|
12
|
+
when Concurrent.on_jruby?
|
13
|
+
require 'concurrent/utility/native_extension_loader'
|
14
|
+
def self.full_memory_barrier
|
15
|
+
JRubyAttrVolatile.full_memory_barrier
|
16
|
+
end
|
17
|
+
|
18
|
+
when Concurrent.on_truffleruby?
|
19
|
+
def self.full_memory_barrier
|
20
|
+
TruffleRuby.full_memory_barrier
|
21
|
+
end
|
22
|
+
|
23
|
+
else
|
24
|
+
warn 'Possibly unsupported Ruby implementation'
|
25
|
+
def self.full_memory_barrier
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
|
1
3
|
module Concurrent
|
2
4
|
module Synchronization
|
3
5
|
|
4
|
-
if Concurrent.on_jruby?
|
6
|
+
if Concurrent.on_jruby?
|
5
7
|
|
6
8
|
# @!visibility private
|
7
9
|
# @!macro internal_implementation_note
|
@@ -1,3 +1,8 @@
|
|
1
|
+
require 'concurrent/utility/engine'
|
2
|
+
require 'concurrent/synchronization/abstract_lockable_object'
|
3
|
+
require 'concurrent/synchronization/mutex_lockable_object'
|
4
|
+
require 'concurrent/synchronization/jruby_lockable_object'
|
5
|
+
|
1
6
|
module Concurrent
|
2
7
|
module Synchronization
|
3
8
|
|
@@ -8,8 +13,6 @@ module Concurrent
|
|
8
13
|
MutexLockableObject
|
9
14
|
when Concurrent.on_jruby?
|
10
15
|
JRubyLockableObject
|
11
|
-
when Concurrent.on_rbx?
|
12
|
-
RbxLockableObject
|
13
16
|
when Concurrent.on_truffleruby?
|
14
17
|
MutexLockableObject
|
15
18
|
else
|
@@ -1,5 +1,6 @@
|
|
1
|
+
require 'concurrent/synchronization/abstract_lockable_object'
|
2
|
+
|
1
3
|
module Concurrent
|
2
|
-
# noinspection RubyInstanceVariableNamingConvention
|
3
4
|
module Synchronization
|
4
5
|
|
5
6
|
# @!visibility private
|
@@ -26,8 +27,8 @@ module Concurrent
|
|
26
27
|
|
27
28
|
safe_initialization!
|
28
29
|
|
29
|
-
def initialize
|
30
|
-
super(
|
30
|
+
def initialize
|
31
|
+
super()
|
31
32
|
@__Lock__ = ::Mutex.new
|
32
33
|
@__Condition__ = ::ConditionVariable.new
|
33
34
|
end
|
@@ -61,8 +62,8 @@ module Concurrent
|
|
61
62
|
|
62
63
|
safe_initialization!
|
63
64
|
|
64
|
-
def initialize
|
65
|
-
super(
|
65
|
+
def initialize
|
66
|
+
super()
|
66
67
|
@__Lock__ = ::Monitor.new
|
67
68
|
@__Condition__ = @__Lock__.new_cond
|
68
69
|
end
|
@@ -1,28 +1,20 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
|
3
|
+
require 'concurrent/synchronization/safe_initialization'
|
4
|
+
require 'concurrent/synchronization/volatile'
|
5
|
+
require 'concurrent/atomic/atomic_reference'
|
6
|
+
|
1
7
|
module Concurrent
|
2
8
|
module Synchronization
|
3
9
|
|
4
|
-
# @!visibility private
|
5
|
-
# @!macro internal_implementation_note
|
6
|
-
ObjectImplementation = case
|
7
|
-
when Concurrent.on_cruby?
|
8
|
-
MriObject
|
9
|
-
when Concurrent.on_jruby?
|
10
|
-
JRubyObject
|
11
|
-
when Concurrent.on_rbx?
|
12
|
-
RbxObject
|
13
|
-
when Concurrent.on_truffleruby?
|
14
|
-
TruffleRubyObject
|
15
|
-
else
|
16
|
-
warn 'Possibly unsupported Ruby implementation'
|
17
|
-
MriObject
|
18
|
-
end
|
19
|
-
private_constant :ObjectImplementation
|
20
|
-
|
21
10
|
# Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions.
|
22
11
|
# - final instance variables see {Object.safe_initialization!}
|
23
12
|
# - volatile instance variables see {Object.attr_volatile}
|
24
13
|
# - volatile instance variables see {Object.attr_atomic}
|
25
|
-
|
14
|
+
# @!visibility private
|
15
|
+
class Object < AbstractObject
|
16
|
+
include Volatile
|
17
|
+
|
26
18
|
# TODO make it a module if possible
|
27
19
|
|
28
20
|
# @!method self.attr_volatile(*names)
|
@@ -38,36 +30,12 @@ module Concurrent
|
|
38
30
|
__initialize_atomic_fields__
|
39
31
|
end
|
40
32
|
|
41
|
-
# By calling this method on a class, it and all its children are marked to be constructed safely. Meaning that
|
42
|
-
# all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures
|
43
|
-
# same behaviour as Java's final fields.
|
44
|
-
# @example
|
45
|
-
# class AClass < Concurrent::Synchronization::Object
|
46
|
-
# safe_initialization!
|
47
|
-
#
|
48
|
-
# def initialize
|
49
|
-
# @AFinalValue = 'value' # published safely, does not have to be synchronized
|
50
|
-
# end
|
51
|
-
# end
|
52
|
-
# @return [true]
|
53
33
|
def self.safe_initialization!
|
54
|
-
|
55
|
-
return if safe_initialization?
|
56
|
-
|
57
|
-
# @!visibility private
|
58
|
-
def self.new(*args, &block)
|
59
|
-
object = super(*args, &block)
|
60
|
-
ensure
|
61
|
-
object.full_memory_barrier if object
|
62
|
-
end
|
63
|
-
|
64
|
-
@safe_initialization = true
|
34
|
+
extend SafeInitialization unless safe_initialization?
|
65
35
|
end
|
66
36
|
|
67
|
-
# @return [true, false] if this class is safely initialized.
|
68
37
|
def self.safe_initialization?
|
69
|
-
|
70
|
-
@safe_initialization || (superclass.respond_to?(:safe_initialization?) && superclass.safe_initialization?)
|
38
|
+
self.singleton_class < SafeInitialization
|
71
39
|
end
|
72
40
|
|
73
41
|
# For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'concurrent/synchronization/full_memory_barrier'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
module Synchronization
|
5
|
+
|
6
|
+
# @!visibility private
|
7
|
+
# @!macro internal_implementation_note
|
8
|
+
#
|
9
|
+
# By extending this module, a class and all its children are marked to be constructed safely. Meaning that
|
10
|
+
# all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures
|
11
|
+
# same behaviour as Java's final fields.
|
12
|
+
#
|
13
|
+
# Due to using Kernel#extend, the module is not included again if already present in the ancestors,
|
14
|
+
# which avoids extra overhead.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# class AClass < Concurrent::Synchronization::Object
|
18
|
+
# extend Concurrent::Synchronization::SafeInitialization
|
19
|
+
#
|
20
|
+
# def initialize
|
21
|
+
# @AFinalValue = 'value' # published safely, #foo will never return nil
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def foo
|
25
|
+
# @AFinalValue
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
module SafeInitialization
|
29
|
+
def new(*args, &block)
|
30
|
+
super(*args, &block)
|
31
|
+
ensure
|
32
|
+
Concurrent::Synchronization.full_memory_barrier
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'concurrent/utility/native_extension_loader' # load native parts first
|
2
|
+
require 'concurrent/utility/engine'
|
3
|
+
require 'concurrent/synchronization/full_memory_barrier'
|
4
|
+
|
1
5
|
module Concurrent
|
2
6
|
module Synchronization
|
3
7
|
|
@@ -19,18 +23,79 @@ module Concurrent
|
|
19
23
|
# => 1
|
20
24
|
# foo.bar = 2
|
21
25
|
# => 2
|
26
|
+
#
|
27
|
+
# @!visibility private
|
28
|
+
module Volatile
|
29
|
+
def self.included(base)
|
30
|
+
base.extend(ClassMethods)
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_memory_barrier
|
34
|
+
Synchronization.full_memory_barrier
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
if Concurrent.on_cruby?
|
39
|
+
def attr_volatile(*names)
|
40
|
+
names.each do |name|
|
41
|
+
ivar = :"@volatile_#{name}"
|
42
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
43
|
+
def #{name}
|
44
|
+
#{ivar}
|
45
|
+
end
|
46
|
+
|
47
|
+
def #{name}=(value)
|
48
|
+
#{ivar} = value
|
49
|
+
end
|
50
|
+
RUBY
|
51
|
+
end
|
52
|
+
names.map { |n| [n, :"#{n}="] }.flatten
|
53
|
+
end
|
54
|
+
|
55
|
+
elsif Concurrent.on_jruby?
|
56
|
+
def attr_volatile(*names)
|
57
|
+
names.each do |name|
|
58
|
+
ivar = :"@volatile_#{name}"
|
59
|
+
|
60
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
61
|
+
def #{name}
|
62
|
+
::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_get_volatile(self, :#{ivar})
|
63
|
+
end
|
64
|
+
|
65
|
+
def #{name}=(value)
|
66
|
+
::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_set_volatile(self, :#{ivar}, value)
|
67
|
+
end
|
68
|
+
RUBY
|
69
|
+
|
70
|
+
end
|
71
|
+
names.map { |n| [n, :"#{n}="] }.flatten
|
72
|
+
end
|
73
|
+
|
74
|
+
else
|
75
|
+
warn 'Possibly unsupported Ruby implementation' unless Concurrent.on_truffleruby?
|
76
|
+
|
77
|
+
def attr_volatile(*names)
|
78
|
+
names.each do |name|
|
79
|
+
ivar = :"@volatile_#{name}"
|
80
|
+
|
81
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
82
|
+
def #{name}
|
83
|
+
::Concurrent::Synchronization.full_memory_barrier
|
84
|
+
#{ivar}
|
85
|
+
end
|
86
|
+
|
87
|
+
def #{name}=(value)
|
88
|
+
#{ivar} = value
|
89
|
+
::Concurrent::Synchronization.full_memory_barrier
|
90
|
+
end
|
91
|
+
RUBY
|
92
|
+
end
|
93
|
+
|
94
|
+
names.map { |n| [n, :"#{n}="] }.flatten
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
22
98
|
|
23
|
-
|
24
|
-
when Concurrent.on_cruby?
|
25
|
-
MriAttrVolatile
|
26
|
-
when Concurrent.on_jruby?
|
27
|
-
JRubyAttrVolatile
|
28
|
-
when Concurrent.on_rbx?
|
29
|
-
RbxAttrVolatile
|
30
|
-
when Concurrent.on_truffleruby?
|
31
|
-
TruffleRubyAttrVolatile
|
32
|
-
else
|
33
|
-
MriAttrVolatile
|
34
|
-
end
|
99
|
+
end
|
35
100
|
end
|
36
101
|
end
|
@@ -1,29 +1,12 @@
|
|
1
|
-
require 'concurrent/utility/engine'
|
2
|
-
|
3
|
-
require 'concurrent/synchronization/abstract_object'
|
4
1
|
require 'concurrent/utility/native_extension_loader' # load native parts first
|
5
|
-
Concurrent.load_native_extensions
|
6
2
|
|
7
|
-
require 'concurrent/synchronization/mri_object'
|
8
|
-
require 'concurrent/synchronization/jruby_object'
|
9
|
-
require 'concurrent/synchronization/rbx_object'
|
10
|
-
require 'concurrent/synchronization/truffleruby_object'
|
11
3
|
require 'concurrent/synchronization/object'
|
12
|
-
require 'concurrent/synchronization/volatile'
|
13
|
-
|
14
|
-
require 'concurrent/synchronization/abstract_lockable_object'
|
15
|
-
require 'concurrent/synchronization/mutex_lockable_object'
|
16
|
-
require 'concurrent/synchronization/jruby_lockable_object'
|
17
|
-
require 'concurrent/synchronization/rbx_lockable_object'
|
18
|
-
|
19
4
|
require 'concurrent/synchronization/lockable_object'
|
20
|
-
|
21
5
|
require 'concurrent/synchronization/condition'
|
22
6
|
require 'concurrent/synchronization/lock'
|
23
7
|
|
24
8
|
module Concurrent
|
25
|
-
#
|
26
|
-
# {include:file:docs-source/synchronization-notes.md}
|
9
|
+
# @!visibility private
|
27
10
|
module Synchronization
|
28
11
|
end
|
29
12
|
end
|