Ruby Singleton

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


EditText of this page (last edited March 12, 2010) or FindPage with title or text search