concurrent-ruby 1.0.5 → 1.1.0.pre1
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 +42 -0
- data/Gemfile +39 -0
- data/{LICENSE.txt → LICENSE.md} +2 -0
- data/README.md +203 -105
- data/Rakefile +278 -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 +304 -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.rb +1 -0
- data/lib/concurrent.rb +24 -20
- data/lib/concurrent/agent.rb +7 -7
- data/lib/concurrent/array.rb +59 -32
- data/lib/concurrent/async.rb +4 -4
- data/lib/concurrent/atom.rb +9 -9
- data/lib/concurrent/atomic/atomic_boolean.rb +24 -20
- data/lib/concurrent/atomic/atomic_fixnum.rb +27 -23
- data/lib/concurrent/atomic/atomic_markable_reference.rb +164 -0
- data/lib/concurrent/atomic/atomic_reference.rb +176 -33
- data/lib/concurrent/atomic/count_down_latch.rb +6 -6
- data/lib/concurrent/atomic/cyclic_barrier.rb +1 -1
- data/lib/concurrent/atomic/event.rb +1 -1
- data/lib/concurrent/atomic/java_count_down_latch.rb +6 -5
- data/lib/concurrent/atomic/mutex_count_down_latch.rb +1 -0
- data/lib/concurrent/atomic/read_write_lock.rb +2 -1
- data/lib/concurrent/atomic/reentrant_read_write_lock.rb +3 -1
- data/lib/concurrent/atomic/semaphore.rb +8 -8
- data/lib/concurrent/atomic/thread_local_var.rb +7 -7
- data/lib/concurrent/atomic_reference/mutex_atomic.rb +3 -8
- data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +1 -1
- data/lib/concurrent/atomics.rb +0 -43
- data/lib/concurrent/collection/lock_free_stack.rb +127 -0
- data/lib/concurrent/collection/map/atomic_reference_map_backend.rb +3 -3
- data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +1 -2
- data/lib/concurrent/collection/non_concurrent_priority_queue.rb +29 -29
- data/lib/concurrent/concern/dereferenceable.rb +1 -1
- data/lib/concurrent/concern/logging.rb +6 -1
- data/lib/concurrent/concern/observable.rb +7 -7
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/configuration.rb +1 -6
- data/lib/concurrent/constants.rb +1 -1
- data/lib/concurrent/dataflow.rb +2 -1
- data/lib/concurrent/delay.rb +9 -7
- data/lib/concurrent/exchanger.rb +13 -21
- data/lib/concurrent/executor/abstract_executor_service.rb +2 -2
- data/lib/concurrent/executor/cached_thread_pool.rb +1 -1
- data/lib/concurrent/executor/executor_service.rb +15 -15
- data/lib/concurrent/executor/fixed_thread_pool.rb +18 -18
- data/lib/concurrent/executor/java_thread_pool_executor.rb +10 -7
- data/lib/concurrent/executor/single_thread_executor.rb +2 -2
- data/lib/concurrent/executor/thread_pool_executor.rb +6 -6
- data/lib/concurrent/executor/timer_set.rb +1 -1
- data/lib/concurrent/future.rb +4 -1
- data/lib/concurrent/hash.rb +53 -30
- data/lib/concurrent/ivar.rb +5 -6
- data/lib/concurrent/map.rb +20 -25
- data/lib/concurrent/maybe.rb +1 -1
- data/lib/concurrent/mutable_struct.rb +15 -14
- data/lib/concurrent/mvar.rb +2 -2
- data/lib/concurrent/promise.rb +53 -21
- data/lib/concurrent/promises.rb +1938 -0
- data/lib/concurrent/re_include.rb +58 -0
- data/lib/concurrent/set.rb +66 -0
- data/lib/concurrent/settable_struct.rb +1 -0
- data/lib/concurrent/synchronization.rb +4 -5
- data/lib/concurrent/synchronization/abstract_lockable_object.rb +5 -5
- data/lib/concurrent/synchronization/abstract_struct.rb +6 -4
- data/lib/concurrent/synchronization/lockable_object.rb +6 -6
- data/lib/concurrent/synchronization/{mri_lockable_object.rb → mutex_lockable_object.rb} +19 -14
- data/lib/concurrent/synchronization/object.rb +8 -4
- data/lib/concurrent/synchronization/truffleruby_object.rb +46 -0
- data/lib/concurrent/synchronization/volatile.rb +11 -9
- data/lib/concurrent/thread_safe/util/data_structures.rb +55 -0
- data/lib/concurrent/thread_safe/util/striped64.rb +9 -4
- data/lib/concurrent/timer_task.rb +5 -2
- data/lib/concurrent/tuple.rb +1 -1
- data/lib/concurrent/tvar.rb +2 -2
- data/lib/concurrent/utility/at_exit.rb +1 -1
- data/lib/concurrent/utility/engine.rb +2 -2
- data/lib/concurrent/utility/monotonic_time.rb +3 -3
- data/lib/concurrent/utility/native_extension_loader.rb +31 -33
- data/lib/concurrent/utility/processor_counter.rb +0 -2
- data/lib/concurrent/version.rb +2 -2
- metadata +35 -21
- 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/edge.rb +0 -26
- data/lib/concurrent/lazy_register.rb +0 -81
- 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
@@ -0,0 +1,58 @@
|
|
1
|
+
module Concurrent
|
2
|
+
|
3
|
+
# Methods form module A included to a module B, which is already included into class C,
|
4
|
+
# will not be visible in the C class. If this module is extended to B then A's methods
|
5
|
+
# are correctly made visible to C.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# module A
|
9
|
+
# def a
|
10
|
+
# :a
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# module B1
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class C1
|
18
|
+
# include B1
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# module B2
|
22
|
+
# extend Concurrent::ReInclude
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# class C2
|
26
|
+
# include B2
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# B1.send :include, A
|
30
|
+
# B2.send :include, A
|
31
|
+
#
|
32
|
+
# C1.new.respond_to? :a # => false
|
33
|
+
# C2.new.respond_to? :a # => true
|
34
|
+
module ReInclude
|
35
|
+
# @!visibility private
|
36
|
+
def included(base)
|
37
|
+
(@re_include_to_bases ||= []) << [:include, base]
|
38
|
+
super(base)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @!visibility private
|
42
|
+
def extended(base)
|
43
|
+
(@re_include_to_bases ||= []) << [:extend, base]
|
44
|
+
super(base)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @!visibility private
|
48
|
+
def include(*modules)
|
49
|
+
result = super(*modules)
|
50
|
+
modules.reverse.each do |module_being_included|
|
51
|
+
(@re_include_to_bases ||= []).each do |method, mod|
|
52
|
+
mod.send method, module_being_included
|
53
|
+
end
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'concurrent/utility/engine'
|
2
|
+
require 'concurrent/thread_safe/util'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Concurrent
|
6
|
+
|
7
|
+
# @!macro concurrent_set
|
8
|
+
#
|
9
|
+
# A thread-safe subclass of Set. 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
|
+
#
|
13
|
+
# @note `a += b` is **not** a **thread-safe** operation on
|
14
|
+
# `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set`
|
15
|
+
# which is union of `a` and `b`, then it writes the union to `a`.
|
16
|
+
# The read and write are independent operations they do not form a single atomic
|
17
|
+
# operation therefore when two `+=` operations are executed concurrently updates
|
18
|
+
# may be lost. Use `#merge` instead.
|
19
|
+
#
|
20
|
+
# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set`
|
21
|
+
|
22
|
+
|
23
|
+
# @!macro internal_implementation_note
|
24
|
+
SetImplementation = case
|
25
|
+
when Concurrent.on_cruby?
|
26
|
+
# Because MRI never runs code in parallel, the existing
|
27
|
+
# non-thread-safe structures should usually work fine.
|
28
|
+
::Set
|
29
|
+
|
30
|
+
when Concurrent.on_jruby?
|
31
|
+
require 'jruby/synchronized'
|
32
|
+
|
33
|
+
class JRubySet < ::Set
|
34
|
+
include JRuby::Synchronized
|
35
|
+
end
|
36
|
+
JRubySet
|
37
|
+
|
38
|
+
when Concurrent.on_rbx?
|
39
|
+
require 'monitor'
|
40
|
+
require 'concurrent/thread_safe/util/data_structures'
|
41
|
+
|
42
|
+
class RbxSet < ::Set
|
43
|
+
end
|
44
|
+
ThreadSafe::Util.make_synchronized_on_rbx Concurrent::Set
|
45
|
+
RbxSet
|
46
|
+
|
47
|
+
when Concurrent.on_truffleruby?
|
48
|
+
require 'concurrent/thread_safe/util/data_structures'
|
49
|
+
|
50
|
+
class TruffleRubySet < ::Set
|
51
|
+
end
|
52
|
+
|
53
|
+
ThreadSafe::Util.make_synchronized_on_truffleruby Concurrent::Set
|
54
|
+
TruffleRubySet
|
55
|
+
|
56
|
+
else
|
57
|
+
warn 'Possibly unsupported Ruby implementation'
|
58
|
+
::Set
|
59
|
+
end
|
60
|
+
private_constant :SetImplementation
|
61
|
+
|
62
|
+
# @!macro concurrent_set
|
63
|
+
class Set < SetImplementation
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -107,6 +107,7 @@ module Concurrent
|
|
107
107
|
synchronize do
|
108
108
|
clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block)
|
109
109
|
members.each_with_index do |member, index|
|
110
|
+
clazz.send :remove_method, member if clazz.instance_methods.include? member
|
110
111
|
clazz.send(:define_method, member) do
|
111
112
|
synchronize { @values[index] }
|
112
113
|
end
|
@@ -7,15 +7,14 @@ Concurrent.load_native_extensions
|
|
7
7
|
require 'concurrent/synchronization/mri_object'
|
8
8
|
require 'concurrent/synchronization/jruby_object'
|
9
9
|
require 'concurrent/synchronization/rbx_object'
|
10
|
-
require 'concurrent/synchronization/
|
10
|
+
require 'concurrent/synchronization/truffleruby_object'
|
11
11
|
require 'concurrent/synchronization/object'
|
12
12
|
require 'concurrent/synchronization/volatile'
|
13
13
|
|
14
14
|
require 'concurrent/synchronization/abstract_lockable_object'
|
15
|
-
require 'concurrent/synchronization/
|
15
|
+
require 'concurrent/synchronization/mutex_lockable_object'
|
16
16
|
require 'concurrent/synchronization/jruby_lockable_object'
|
17
17
|
require 'concurrent/synchronization/rbx_lockable_object'
|
18
|
-
require 'concurrent/synchronization/truffle_lockable_object'
|
19
18
|
|
20
19
|
require 'concurrent/synchronization/lockable_object'
|
21
20
|
|
@@ -23,8 +22,8 @@ require 'concurrent/synchronization/condition'
|
|
23
22
|
require 'concurrent/synchronization/lock'
|
24
23
|
|
25
24
|
module Concurrent
|
26
|
-
# {include:file:
|
27
|
-
# {include:file:
|
25
|
+
# {include:file:docs-source/synchronization.md}
|
26
|
+
# {include:file:docs-source/synchronization-notes.md}
|
28
27
|
module Synchronization
|
29
28
|
end
|
30
29
|
end
|
@@ -6,7 +6,7 @@ module Concurrent
|
|
6
6
|
|
7
7
|
protected
|
8
8
|
|
9
|
-
# @!macro
|
9
|
+
# @!macro synchronization_object_method_synchronize
|
10
10
|
#
|
11
11
|
# @yield runs the block synchronized against this object,
|
12
12
|
# equivalent of java's `synchronize(this) {}`
|
@@ -15,7 +15,7 @@ module Concurrent
|
|
15
15
|
raise NotImplementedError
|
16
16
|
end
|
17
17
|
|
18
|
-
# @!macro
|
18
|
+
# @!macro synchronization_object_method_ns_wait_until
|
19
19
|
#
|
20
20
|
# Wait until condition is met or timeout passes,
|
21
21
|
# protects against spurious wake-ups.
|
@@ -45,7 +45,7 @@ module Concurrent
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
# @!macro
|
48
|
+
# @!macro synchronization_object_method_ns_wait
|
49
49
|
#
|
50
50
|
# Wait until another thread calls #signal or #broadcast,
|
51
51
|
# spurious wake-ups can happen.
|
@@ -63,7 +63,7 @@ module Concurrent
|
|
63
63
|
raise NotImplementedError
|
64
64
|
end
|
65
65
|
|
66
|
-
# @!macro
|
66
|
+
# @!macro synchronization_object_method_ns_signal
|
67
67
|
#
|
68
68
|
# Signal one waiting thread.
|
69
69
|
# @return [self]
|
@@ -78,7 +78,7 @@ module Concurrent
|
|
78
78
|
raise NotImplementedError
|
79
79
|
end
|
80
80
|
|
81
|
-
# @!macro
|
81
|
+
# @!macro synchronization_object_method_ns_broadcast
|
82
82
|
#
|
83
83
|
# Broadcast to all waiting threads.
|
84
84
|
# @return [self]
|
@@ -11,7 +11,7 @@ module Concurrent
|
|
11
11
|
ns_initialize(*values)
|
12
12
|
end
|
13
13
|
|
14
|
-
# @!macro
|
14
|
+
# @!macro struct_length
|
15
15
|
#
|
16
16
|
# Returns the number of struct members.
|
17
17
|
#
|
@@ -21,7 +21,7 @@ module Concurrent
|
|
21
21
|
end
|
22
22
|
alias_method :size, :length
|
23
23
|
|
24
|
-
# @!macro
|
24
|
+
# @!macro struct_members
|
25
25
|
#
|
26
26
|
# Returns the struct members as an array of symbols.
|
27
27
|
#
|
@@ -117,7 +117,7 @@ module Concurrent
|
|
117
117
|
|
118
118
|
# @!visibility private
|
119
119
|
def pr_underscore(clazz)
|
120
|
-
word = clazz.to_s
|
120
|
+
word = clazz.to_s.dup # dup string to workaround JRuby 9.2.0.0 bug https://github.com/jruby/jruby/issues/5229
|
121
121
|
word.gsub!(/::/, '/')
|
122
122
|
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
123
123
|
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
@@ -138,13 +138,15 @@ module Concurrent
|
|
138
138
|
end
|
139
139
|
unless name.nil?
|
140
140
|
begin
|
141
|
+
parent.send :remove_const, name if parent.const_defined? name
|
141
142
|
parent.const_set(name, clazz)
|
142
|
-
|
143
|
+
clazz
|
143
144
|
rescue NameError
|
144
145
|
raise NameError.new("identifier #{name} needs to be constant")
|
145
146
|
end
|
146
147
|
end
|
147
148
|
members.each_with_index do |member, index|
|
149
|
+
clazz.send :remove_method, member if clazz.instance_methods.include? member
|
148
150
|
clazz.send(:define_method, member) do
|
149
151
|
@values[index]
|
150
152
|
end
|
@@ -5,18 +5,18 @@ module Concurrent
|
|
5
5
|
# @!macro internal_implementation_note
|
6
6
|
LockableObjectImplementation = case
|
7
7
|
when Concurrent.on_cruby? && Concurrent.ruby_version(:<=, 1, 9, 3)
|
8
|
-
|
8
|
+
MonitorLockableObject
|
9
9
|
when Concurrent.on_cruby? && Concurrent.ruby_version(:>, 1, 9, 3)
|
10
|
-
|
10
|
+
MutexLockableObject
|
11
11
|
when Concurrent.on_jruby?
|
12
12
|
JRubyLockableObject
|
13
13
|
when Concurrent.on_rbx?
|
14
14
|
RbxLockableObject
|
15
|
-
when Concurrent.
|
16
|
-
|
15
|
+
when Concurrent.on_truffleruby?
|
16
|
+
MutexLockableObject
|
17
17
|
else
|
18
18
|
warn 'Possibly unsupported Ruby implementation'
|
19
|
-
|
19
|
+
MonitorLockableObject
|
20
20
|
end
|
21
21
|
private_constant :LockableObjectImplementation
|
22
22
|
|
@@ -31,7 +31,7 @@ module Concurrent
|
|
31
31
|
# `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and
|
32
32
|
# `Thread#wakeup` will not work on all platforms.
|
33
33
|
#
|
34
|
-
# @see
|
34
|
+
# @see Event implementation as an example of this class use
|
35
35
|
#
|
36
36
|
# @example simple
|
37
37
|
# class AnClass < Synchronization::Object
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module Concurrent
|
2
|
+
# noinspection RubyInstanceVariableNamingConvention
|
2
3
|
module Synchronization
|
3
4
|
|
4
5
|
# @!visibility private
|
5
6
|
# @!macro internal_implementation_note
|
6
|
-
|
7
|
+
module ConditionSignalling
|
7
8
|
protected
|
8
9
|
|
9
10
|
def ns_signal
|
10
|
-
@
|
11
|
+
@__Condition__.signal
|
11
12
|
self
|
12
13
|
end
|
13
14
|
|
14
15
|
def ns_broadcast
|
15
|
-
@
|
16
|
+
@__Condition__.broadcast
|
16
17
|
self
|
17
18
|
end
|
18
19
|
end
|
@@ -20,50 +21,54 @@ module Concurrent
|
|
20
21
|
|
21
22
|
# @!visibility private
|
22
23
|
# @!macro internal_implementation_note
|
23
|
-
class
|
24
|
+
class MutexLockableObject < AbstractLockableObject
|
25
|
+
include ConditionSignalling
|
26
|
+
|
24
27
|
safe_initialization!
|
25
28
|
|
26
29
|
def initialize(*defaults)
|
27
30
|
super(*defaults)
|
28
|
-
@
|
29
|
-
@
|
31
|
+
@__Lock__ = ::Mutex.new
|
32
|
+
@__Condition__ = ::ConditionVariable.new
|
30
33
|
end
|
31
34
|
|
32
35
|
protected
|
33
36
|
|
34
37
|
def synchronize
|
35
|
-
if @
|
38
|
+
if @__Lock__.owned?
|
36
39
|
yield
|
37
40
|
else
|
38
|
-
@
|
41
|
+
@__Lock__.synchronize { yield }
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
45
|
def ns_wait(timeout = nil)
|
43
|
-
@
|
46
|
+
@__Condition__.wait @__Lock__, timeout
|
44
47
|
self
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
51
|
# @!visibility private
|
49
52
|
# @!macro internal_implementation_note
|
50
|
-
class
|
53
|
+
class MonitorLockableObject < AbstractLockableObject
|
54
|
+
include ConditionSignalling
|
55
|
+
|
51
56
|
safe_initialization!
|
52
57
|
|
53
58
|
def initialize(*defaults)
|
54
59
|
super(*defaults)
|
55
|
-
@
|
56
|
-
@
|
60
|
+
@__Lock__ = ::Monitor.new
|
61
|
+
@__Condition__ = @__Lock__.new_cond
|
57
62
|
end
|
58
63
|
|
59
64
|
protected
|
60
65
|
|
61
66
|
def synchronize # TODO may be a problem with lock.synchronize { lock.wait }
|
62
|
-
@
|
67
|
+
@__Lock__.synchronize { yield }
|
63
68
|
end
|
64
69
|
|
65
70
|
def ns_wait(timeout = nil)
|
66
|
-
@
|
71
|
+
@__Condition__.wait timeout
|
67
72
|
self
|
68
73
|
end
|
69
74
|
end
|
@@ -10,9 +10,10 @@ module Concurrent
|
|
10
10
|
JRubyObject
|
11
11
|
when Concurrent.on_rbx?
|
12
12
|
RbxObject
|
13
|
-
when Concurrent.
|
14
|
-
|
13
|
+
when Concurrent.on_truffleruby?
|
14
|
+
TruffleRubyObject
|
15
15
|
else
|
16
|
+
warn 'Possibly unsupported Ruby implementation'
|
16
17
|
MriObject
|
17
18
|
end
|
18
19
|
private_constant :ObjectImplementation
|
@@ -134,8 +135,11 @@ module Concurrent
|
|
134
135
|
private
|
135
136
|
|
136
137
|
def self.define_initialize_volatile_with_cas
|
137
|
-
assignments = @volatile_cas_fields.map
|
138
|
-
|
138
|
+
assignments = @volatile_cas_fields.map do |name|
|
139
|
+
"@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)"
|
140
|
+
end.join("\n")
|
141
|
+
|
142
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
139
143
|
def initialize_volatile_with_cas
|
140
144
|
super
|
141
145
|
#{assignments}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Concurrent
|
2
|
+
module Synchronization
|
3
|
+
|
4
|
+
module TruffleRubyAttrVolatile
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def attr_volatile(*names)
|
11
|
+
names.each do |name|
|
12
|
+
ivar = :"@volatile_#{name}"
|
13
|
+
|
14
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
15
|
+
def #{name}
|
16
|
+
full_memory_barrier
|
17
|
+
#{ivar}
|
18
|
+
end
|
19
|
+
|
20
|
+
def #{name}=(value)
|
21
|
+
#{ivar} = value
|
22
|
+
full_memory_barrier
|
23
|
+
end
|
24
|
+
RUBY
|
25
|
+
end
|
26
|
+
|
27
|
+
names.map { |n| [n, :"#{n}="] }.flatten
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def full_memory_barrier
|
32
|
+
TruffleRuby.full_memory_barrier
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @!visibility private
|
37
|
+
# @!macro internal_implementation_note
|
38
|
+
class TruffleRubyObject < AbstractObject
|
39
|
+
include TruffleRubyAttrVolatile
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
# nothing to do
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -21,14 +21,16 @@ module Concurrent
|
|
21
21
|
# => 2
|
22
22
|
|
23
23
|
Volatile = case
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
33
35
|
end
|
34
36
|
end
|