Skip to content

Commit 94d71f1

Browse files
committed
Fix circular dependency between AtomicReference and Synchronization::Object
* Specifically, the cycle is: Synchronization::Object -> AtomicReference (through generated code for #__initialize_atomic_fields__ used by #initialize) AtomicReference -> MutexAtomicReference (only for cruby no exts and unknown ruby) MutexAtomicReference -> Synchronization::LockableObject Synchronization::LockableObject -> MutexLockableObject, JRubyLockableObject, MonitorLockableObject MutexLockableObject -> AbstractLockableObject AbstractLockableObject -> Synchronization::Object As an example AtomicMarkableReference -> Synchronization::Object uses it and so the requires of spec/concurrent/atomic/atomic_markable_reference_spec.rb cannot be fixed before this. * This also avoids allocating a ConditionVariable for MutexAtomicReference.
1 parent 5406c1c commit 94d71f1

File tree

5 files changed

+20
-11
lines changed

5 files changed

+20
-11
lines changed

lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
require 'concurrent/synchronization'
1+
require 'concurrent/utility/native_extension_loader' # load native parts first
2+
23
require 'concurrent/utility/engine'
34
require 'concurrent/atomic_reference/numeric_cas_wrapper'
45

lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ module Concurrent
22

33
# @!visibility private
44
# @!macro internal_implementation_note
5-
class MutexAtomicReference < Synchronization::LockableObject
5+
class MutexAtomicReference
66
include AtomicDirectUpdate
77
include AtomicNumericCompareAndSetWrapper
88
alias_method :compare_and_swap, :compare_and_set
99

1010
# @!macro atomic_reference_method_initialize
1111
def initialize(value = nil)
1212
super()
13+
@__Lock__ = ::Mutex.new
14+
# This synchronize should be good enough to ensure safe initialization
1315
synchronize { ns_initialize(value) }
1416
end
1517

@@ -49,6 +51,14 @@ def _compare_and_set(old_value, new_value)
4951

5052
protected
5153

54+
def synchronize
55+
if @__Lock__.owned?
56+
yield
57+
else
58+
@__Lock__.synchronize { yield }
59+
end
60+
end
61+
5262
def ns_initialize(value)
5363
@value = value
5464
end

lib/concurrent-ruby/concurrent/synchronization.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
require 'concurrent/utility/native_extension_loader' # load native parts first
2+
13
require 'concurrent/utility/engine'
24

35
require 'concurrent/synchronization/abstract_object'
4-
require 'concurrent/utility/native_extension_loader' # load native parts first
5-
Concurrent.load_native_extensions
6-
76
require 'concurrent/synchronization/mri_object'
87
require 'concurrent/synchronization/jruby_object'
98
require 'concurrent/synchronization/truffleruby_object'

lib/concurrent-ruby/concurrent/synchronization/object.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require 'concurrent/atomic/atomic_reference'
2+
13
module Concurrent
24
module Synchronization
35

lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
require 'concurrent/utility/engine'
2+
# Synchronization::AbstractObject must be defined before loading the extension
3+
require 'concurrent/synchronization/abstract_object'
24

35
module Concurrent
4-
56
module Utility
6-
77
# @!visibility private
88
module NativeExtensionLoader
99

@@ -20,10 +20,6 @@ def java_extensions_loaded?
2020
end
2121

2222
def load_native_extensions
23-
unless defined? Synchronization::AbstractObject
24-
raise 'native_extension_loader loaded before Synchronization::AbstractObject'
25-
end
26-
2723
if Concurrent.on_cruby? && !c_extensions_loaded?
2824
['concurrent/concurrent_ruby_ext',
2925
"concurrent/#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
@@ -77,3 +73,4 @@ def try_load_c_extension(path)
7773
extend Utility::NativeExtensionLoader
7874
end
7975

76+
Concurrent.load_native_extensions

0 commit comments

Comments
 (0)