diff --git a/lib/concurrent/synchronization.rb b/lib/concurrent/synchronization.rb index 62575baa5..cf2dec114 100644 --- a/lib/concurrent/synchronization.rb +++ b/lib/concurrent/synchronization.rb @@ -7,15 +7,14 @@ require 'concurrent/synchronization/mri_object' require 'concurrent/synchronization/jruby_object' require 'concurrent/synchronization/rbx_object' -require 'concurrent/synchronization/truffle_object' +require 'concurrent/synchronization/truffleruby_object' require 'concurrent/synchronization/object' require 'concurrent/synchronization/volatile' require 'concurrent/synchronization/abstract_lockable_object' -require 'concurrent/synchronization/mri_lockable_object' +require 'concurrent/synchronization/mutex_lockable_object' require 'concurrent/synchronization/jruby_lockable_object' require 'concurrent/synchronization/rbx_lockable_object' -require 'concurrent/synchronization/truffle_lockable_object' require 'concurrent/synchronization/lockable_object' diff --git a/lib/concurrent/synchronization/lockable_object.rb b/lib/concurrent/synchronization/lockable_object.rb index e87528e2d..28c84beb6 100644 --- a/lib/concurrent/synchronization/lockable_object.rb +++ b/lib/concurrent/synchronization/lockable_object.rb @@ -5,18 +5,18 @@ module Synchronization # @!macro internal_implementation_note LockableObjectImplementation = case when Concurrent.on_cruby? && Concurrent.ruby_version(:<=, 1, 9, 3) - MriMonitorLockableObject + MonitorLockableObject when Concurrent.on_cruby? && Concurrent.ruby_version(:>, 1, 9, 3) - MriMutexLockableObject + MutexLockableObject when Concurrent.on_jruby? JRubyLockableObject when Concurrent.on_rbx? RbxLockableObject when Concurrent.on_truffleruby? - MriMutexLockableObject + MutexLockableObject else warn 'Possibly unsupported Ruby implementation' - MriMonitorLockableObject + MonitorLockableObject end private_constant :LockableObjectImplementation diff --git a/lib/concurrent/synchronization/mri_lockable_object.rb b/lib/concurrent/synchronization/mutex_lockable_object.rb similarity index 56% rename from lib/concurrent/synchronization/mri_lockable_object.rb rename to lib/concurrent/synchronization/mutex_lockable_object.rb index 22120280b..f288c51a1 100644 --- a/lib/concurrent/synchronization/mri_lockable_object.rb +++ b/lib/concurrent/synchronization/mutex_lockable_object.rb @@ -1,18 +1,19 @@ module Concurrent + # noinspection RubyInstanceVariableNamingConvention module Synchronization # @!visibility private # @!macro internal_implementation_note - class MriLockableObject < AbstractLockableObject + module ConditionSignalling protected def ns_signal - @__condition__.signal + @__Condition__.signal self end def ns_broadcast - @__condition__.broadcast + @__Condition__.broadcast self end end @@ -20,50 +21,54 @@ def ns_broadcast # @!visibility private # @!macro internal_implementation_note - class MriMutexLockableObject < MriLockableObject + class MutexLockableObject < AbstractLockableObject + include ConditionSignalling + safe_initialization! def initialize(*defaults) super(*defaults) - @__lock__ = ::Mutex.new - @__condition__ = ::ConditionVariable.new + @__Lock__ = ::Mutex.new + @__Condition__ = ::ConditionVariable.new end protected def synchronize - if @__lock__.owned? + if @__Lock__.owned? yield else - @__lock__.synchronize { yield } + @__Lock__.synchronize { yield } end end def ns_wait(timeout = nil) - @__condition__.wait @__lock__, timeout + @__Condition__.wait @__Lock__, timeout self end end # @!visibility private # @!macro internal_implementation_note - class MriMonitorLockableObject < MriLockableObject + class MonitorLockableObject < AbstractLockableObject + include ConditionSignalling + safe_initialization! def initialize(*defaults) super(*defaults) - @__lock__ = ::Monitor.new - @__condition__ = @__lock__.new_cond + @__Lock__ = ::Monitor.new + @__Condition__ = @__Lock__.new_cond end protected def synchronize # TODO may be a problem with lock.synchronize { lock.wait } - @__lock__.synchronize { yield } + @__Lock__.synchronize { yield } end def ns_wait(timeout = nil) - @__condition__.wait timeout + @__Condition__.wait timeout self end end diff --git a/lib/concurrent/synchronization/object.rb b/lib/concurrent/synchronization/object.rb index c42c7e956..1254427c7 100644 --- a/lib/concurrent/synchronization/object.rb +++ b/lib/concurrent/synchronization/object.rb @@ -11,8 +11,9 @@ module Synchronization when Concurrent.on_rbx? RbxObject when Concurrent.on_truffleruby? - TruffleObject + TruffleRubyObject else + warn 'Possibly unsupported Ruby implementation' MriObject end private_constant :ObjectImplementation @@ -134,8 +135,11 @@ def self.volatile_cas_fields(inherited = true) private def self.define_initialize_volatile_with_cas - assignments = @volatile_cas_fields.map { |name| "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = AtomicReference.new(nil)" }.join("\n") - class_eval <<-RUBY + assignments = @volatile_cas_fields.map do |name| + "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)" + end.join("\n") + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 def initialize_volatile_with_cas super #{assignments} diff --git a/lib/concurrent/synchronization/truffle_lockable_object.rb b/lib/concurrent/synchronization/truffle_lockable_object.rb deleted file mode 100644 index c9328f21f..000000000 --- a/lib/concurrent/synchronization/truffle_lockable_object.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Concurrent - module Synchronization - class TruffleLockableObject < AbstractLockableObject - def new(*) - raise NotImplementedError - end - end - end -end diff --git a/lib/concurrent/synchronization/truffle_object.rb b/lib/concurrent/synchronization/truffle_object.rb deleted file mode 100644 index 9b1c3fc76..000000000 --- a/lib/concurrent/synchronization/truffle_object.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Concurrent - module Synchronization - - module TruffleAttrVolatile - def self.included(base) - base.extend(ClassMethods) - end - - module ClassMethods - def attr_volatile(*names) - # TODO may not always be available - attr_atomic(*names) - end - end - - def full_memory_barrier - Truffle::System.full_memory_barrier - end - end - - # @!visibility private - # @!macro internal_implementation_note - class TruffleObject < AbstractObject - include TruffleAttrVolatile - - def initialize - # nothing to do - end - end - end -end diff --git a/lib/concurrent/synchronization/truffleruby_object.rb b/lib/concurrent/synchronization/truffleruby_object.rb new file mode 100644 index 000000000..b25fe2189 --- /dev/null +++ b/lib/concurrent/synchronization/truffleruby_object.rb @@ -0,0 +1,46 @@ +module Concurrent + module Synchronization + + module TruffleRubyAttrVolatile + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + full_memory_barrier + #{ivar} + end + + def #{name}=(value) + #{ivar} = value + full_memory_barrier + end + RUBY + end + + names.map { |n| [n, :"#{n}="] }.flatten + end + end + + def full_memory_barrier + TruffleRuby.full_memory_barrier + end + end + + # @!visibility private + # @!macro internal_implementation_note + class TruffleRubyObject < AbstractObject + include TruffleRubyAttrVolatile + + def initialize + # nothing to do + end + end + end +end diff --git a/lib/concurrent/synchronization/volatile.rb b/lib/concurrent/synchronization/volatile.rb index e1f2c12ba..9dffa914a 100644 --- a/lib/concurrent/synchronization/volatile.rb +++ b/lib/concurrent/synchronization/volatile.rb @@ -21,14 +21,16 @@ module Synchronization # => 2 Volatile = case - when Concurrent.on_cruby? - MriAttrVolatile - when Concurrent.on_jruby? - JRubyAttrVolatile - when Concurrent.on_rbx? || Concurrent.on_truffleruby? - RbxAttrVolatile - else - MriAttrVolatile - end + when Concurrent.on_cruby? + MriAttrVolatile + when Concurrent.on_jruby? + JRubyAttrVolatile + when Concurrent.on_rbx? + RbxAttrVolatile + when Concurrent.on_truffleruby? + TruffleRubyAttrVolatile + else + MriAttrVolatile + end end end