Skip to content

Commit

Permalink
Merge pull request #4 from rm155/master
Browse files Browse the repository at this point in the history
Create RactorLocalSingleton
  • Loading branch information
hsbt authored Oct 1, 2024
2 parents 17842b0 + 0a77bb4 commit 6780da5
Showing 1 changed file with 87 additions and 20 deletions.
107 changes: 87 additions & 20 deletions lib/singleton.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# frozen_string_literal: false
# frozen_string_literal: true

# The Singleton module implements the Singleton pattern.
#
Expand Down Expand Up @@ -94,20 +94,23 @@
module Singleton
VERSION = "0.2.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:

Expand All @@ -121,7 +124,7 @@ def _load(str)
end

def instance # :nodoc:
@singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= new }
@singleton__instance__ || @singleton__mutex__.synchronize { @singleton__instance__ ||= set_instance(new) }
end

private
Expand All @@ -130,22 +133,42 @@ 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)
Expand All @@ -157,10 +180,11 @@ def append_features(mod)
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
Expand All @@ -170,3 +194,46 @@ def included(klass)
# :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

0 comments on commit 6780da5

Please sign in to comment.