diff options
author | rm155 <[email protected]> | 2021-07-30 15:45:34 -0400 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2024-10-01 17:59:42 +0900 |
commit | 136b30b414b3fcaddf0505d5a72fed8b08b2da3c (patch) | |
tree | ff2106cdadb16f69450b2d5355f6e33391292c59 | |
parent | 76111af632a0689cbe56787b0fb1ba4c8bbbe2e0 (diff) |
[ruby/singleton] Improve Ractor-compliance; Create PerRactorSingleton
https://github.com/ruby/singleton/commit/ec4f66d9c1
-rw-r--r-- | lib/singleton.rb | 104 |
1 files changed, 85 insertions, 19 deletions
diff --git a/lib/singleton.rb b/lib/singleton.rb index 6da939124e..577a7b8894 100644 --- a/lib/singleton.rb +++ b/lib/singleton.rb @@ -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 |