[ruby/singleton] Improve Ractor-compliance; Create PerRactorSingleton

https://github.com/ruby/singleton/commit/ec4f66d9c1
This commit is contained in:
rm155 2021-07-30 15:45:34 -04:00 committed by Hiroshi SHIBATA
parent 76111af632
commit 136b30b414
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2

View File

@ -93,21 +93,25 @@
#
module Singleton
VERSION = "0.2.0"
VERSION.freeze
# Raises a TypeError to prevent cloning.
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
end
module SingletonInstanceMethods
# Raises a TypeError to prevent cloning.
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
end
# Raises a TypeError to prevent duping.
def dup
raise TypeError, "can't dup instance of singleton #{self.class}"
end
# Raises a TypeError to prevent duping.
def dup
raise TypeError, "can't dup instance of singleton #{self.class}"
end
# By default, do not retain any state when marshalling.
def _dump(depth = -1)
''
# By default, do not retain any state when marshalling.
def _dump(depth = -1)
''
end
end
include SingletonInstanceMethods
module SingletonClassMethods # :nodoc:
@ -121,7 +125,7 @@ module Singleton
end
def instance # :nodoc:
@singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= new }
@singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= set_instance(new) }
end
private
@ -130,22 +134,42 @@ module Singleton
super
Singleton.__init__(sub_klass)
end
def set_instance(val)
@singleton__instance__ = val
end
def set_mutex(val)
@singleton__mutex__ = val
end
end
class << Singleton # :nodoc:
def self.module_with_class_methods
SingletonClassMethods
end
module SingletonClassProperties
def self.included(c)
# extending an object with Singleton is a bad idea
c.undef_method :extend_object
end
def self.extended(c)
# extending an object with Singleton is a bad idea
c.singleton_class.undef_method :extend_object
end
def __init__(klass) # :nodoc:
klass.instance_eval {
@singleton__instance__ = nil
@singleton__mutex__ = Thread::Mutex.new
set_instance(nil)
set_mutex(Thread::Mutex.new)
}
klass
end
private
# extending an object with Singleton is a bad idea
undef_method :extend_object
def append_features(mod)
# help out people counting on transitive mixins
unless mod.instance_of?(Class)
@ -157,10 +181,11 @@ module Singleton
def included(klass)
super
klass.private_class_method :new, :allocate
klass.extend SingletonClassMethods
klass.extend module_with_class_methods
Singleton.__init__(klass)
end
end
extend SingletonClassProperties
##
# :singleton-method: _load
@ -170,3 +195,44 @@ module Singleton
# :singleton-method: instance
# Returns the singleton instance.
end
module PerRactorSingleton
include Singleton::SingletonInstanceMethods
module PerRactorSingletonClassMethods
include Singleton::SingletonClassMethods
def instance
set_mutex(Thread::Mutex.new) if Ractor.current[mutex_key].nil?
return Ractor.current[instance_key] if Ractor.current[instance_key]
Ractor.current[mutex_key].synchronize {
return Ractor.current[instance_key] if Ractor.current[instance_key]
set_instance(new())
}
Ractor.current[instance_key]
end
private
def instance_key
:"__PerRactorSingleton_instance_with_class_id_#{object_id}__"
end
def mutex_key
:"__PerRactorSingleton_mutex_with_class_id_#{object_id}__"
end
def set_instance(val)
Ractor.current[instance_key] = val
end
def set_mutex(val)
Ractor.current[mutex_key] = val
end
end
def self.module_with_class_methods
PerRactorSingletonClassMethods
end
extend Singleton::SingletonClassProperties
end