[ruby/singleton] Improve Ractor-compliance; Create PerRactorSingleton
https://github.com/ruby/singleton/commit/ec4f66d9c1
This commit is contained in:
parent
76111af632
commit
136b30b414
104
lib/singleton.rb
104
lib/singleton.rb
@ -93,21 +93,25 @@
|
|||||||
#
|
#
|
||||||
module Singleton
|
module Singleton
|
||||||
VERSION = "0.2.0"
|
VERSION = "0.2.0"
|
||||||
|
VERSION.freeze
|
||||||
|
|
||||||
# Raises a TypeError to prevent cloning.
|
module SingletonInstanceMethods
|
||||||
def clone
|
# Raises a TypeError to prevent cloning.
|
||||||
raise TypeError, "can't clone instance of singleton #{self.class}"
|
def clone
|
||||||
end
|
raise TypeError, "can't clone instance of singleton #{self.class}"
|
||||||
|
end
|
||||||
|
|
||||||
# Raises a TypeError to prevent duping.
|
# Raises a TypeError to prevent duping.
|
||||||
def dup
|
def dup
|
||||||
raise TypeError, "can't dup instance of singleton #{self.class}"
|
raise TypeError, "can't dup instance of singleton #{self.class}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# By default, do not retain any state when marshalling.
|
# By default, do not retain any state when marshalling.
|
||||||
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
|
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:
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user