[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,7 +93,9 @@
# #
module Singleton module Singleton
VERSION = "0.2.0" VERSION = "0.2.0"
VERSION.freeze
module SingletonInstanceMethods
# Raises a TypeError to prevent cloning. # Raises a TypeError to prevent cloning.
def clone def clone
raise TypeError, "can't clone instance of singleton #{self.class}" raise TypeError, "can't clone instance of singleton #{self.class}"
@ -108,6 +110,8 @@ module Singleton
def _dump(depth = -1) def _dump(depth = -1)
'' ''
end end
end
include SingletonInstanceMethods
module SingletonClassMethods # :nodoc: module SingletonClassMethods # :nodoc:
@ -121,7 +125,7 @@ module Singleton
end end
def instance # :nodoc: def instance # :nodoc:
@singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= new } @singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= set_instance(new) }
end end
private private
@ -130,22 +134,42 @@ module Singleton
super super
Singleton.__init__(sub_klass) Singleton.__init__(sub_klass)
end end
def set_instance(val)
@singleton__instance__ = val
end
def set_mutex(val)
@singleton__mutex__ = val
end
end
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 end
class << Singleton # :nodoc:
def __init__(klass) # :nodoc: def __init__(klass) # :nodoc:
klass.instance_eval { klass.instance_eval {
@singleton__instance__ = nil set_instance(nil)
@singleton__mutex__ = Thread::Mutex.new set_mutex(Thread::Mutex.new)
} }
klass klass
end end
private private
# extending an object with Singleton is a bad idea
undef_method :extend_object
def append_features(mod) def append_features(mod)
# help out people counting on transitive mixins # help out people counting on transitive mixins
unless mod.instance_of?(Class) unless mod.instance_of?(Class)
@ -157,10 +181,11 @@ module Singleton
def included(klass) def included(klass)
super super
klass.private_class_method :new, :allocate klass.private_class_method :new, :allocate
klass.extend SingletonClassMethods klass.extend module_with_class_methods
Singleton.__init__(klass) Singleton.__init__(klass)
end end
end end
extend SingletonClassProperties
## ##
# :singleton-method: _load # :singleton-method: _load
@ -170,3 +195,44 @@ module Singleton
# :singleton-method: instance # :singleton-method: instance
# Returns the singleton instance. # Returns the singleton instance.
end 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