RubySingleton

Last edit March 12, 2010
	require 'singleton'
	class Aardvark
	  include Singleton
	end
That's it. Mixing in the Singleton module makes the "new" method private and creates an "instance" method that returns the sole instance of Aardvark. (So you'd access the Aardvark by saying "Aardvark.instance".) It also takes care of thread safety.

For educational purposes, this is how you would implement it without the use of the standard library:
	class Aardvark
          private_class_method :new
          @@instance = new
          def Aardvark.instance
            @@instance
          end
	end
Or, if you want it to be lazy-loading:
	class Aardvark
          private_class_method :new
          def Aardvark.instance
            @@instance = new unless @@instance
            @@instance
          end
	end

The following is an implementation of a module (MixIn) that will turn a class into a thread-safe, lazy-loading singleton.

      module ThreadSafeSingleton
        def self.append_features(clazz)
          require 'thread'
          clazz.module_eval { 
            private_class_method :new
            @instance_mutex = Mutex.new
            def self.instance 
              @instance_mutex.synchronize {
                @instance = new unless @instance
                @instance
              }
            end
          }
        end
      end

# For further educational enjoyment, the following provides a test for # thread-safeness and a contrasting non-thread-safe implementation

require 'test/unit'

module SimpleSingleton def self.append_features(clazz) clazz.module_eval { private_class_method :new def self.instance @instance = new unless @instance @instance end } end end class SimpleSingletonClass include SimpleSingleton def initialize sleep 1 end end

class ThreadSafeSingletonClass include ThreadSafeSingleton def initialize sleep 1 end end

class TestSingleton < Test::Unit::TestCase def testSimpleIsNotThreadSafe threads = Array.new(101) { Thread.new { SimpleSingletonClass.instance }} assert(threads.collect { |t| t.value }.uniq.size > 1) end def testThreadSafeIsThreadSafe threads = Array.new(101) { Thread.new { ThreadSafeSingletonClass.instance }} assert_equal(1, threads.collect { |t| t.value }.uniq.size) end end


Compare with PerlSingleton and PythonSingleton
CategoryRuby