lib/singleton.rb in singleton-0.2.0 vs lib/singleton.rb in singleton-0.3.0
- old
+ new
@@ -1,6 +1,6 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
# The Singleton module implements the Singleton pattern.
#
# == Usage
#
@@ -90,26 +90,29 @@
# p a == b # => true
# p a.keep # => "keep this"
# p a.strip # => nil
#
module Singleton
- VERSION = "0.2.0"
+ VERSION = "0.3.0"
- # 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:
def clone # :nodoc:
Singleton.__init__(super)
@@ -128,26 +131,46 @@
def inherited(sub_klass)
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.send(: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)
raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
end
@@ -155,18 +178,62 @@
end
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
# By default calls instance(). Override to retain singleton state.
##
# :singleton-method: instance
# Returns the singleton instance.
+end
+
+if defined?(Ractor)
+ module RactorLocalSingleton
+ include Singleton::SingletonInstanceMethods
+
+ module RactorLocalSingletonClassMethods
+ 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
+ :"__RactorLocalSingleton_instance_with_class_id_#{object_id}__"
+ end
+
+ def mutex_key
+ :"__RactorLocalSingleton_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
+ RactorLocalSingletonClassMethods
+ end
+
+ extend Singleton::SingletonClassProperties
+ end
end