Hi,

the current (i.e. cvs) implementation of the  OO Singleton pattern has 
no strategy with respect to marshalling - the following script illustrates
the problem.

---------------
require 'singleton'
class A
   include Singleton
end

resurrect = Marshal.load(Marshal.dump(A.instance))
p resurrect == A.instance # => false
---------------

The attached script fixes this problem - it is a variation of
the current cvs strategy and implements the following idea
*  Ensure that only one instance of the class can be (regularly)
   created
*  The ``instance'' is created at ``instanciation time'' - i.e. 
   the first call of #instance
*  This behavior is preserved under inheritance

The script includes a slightly more serious test of a threaded
environment.  A typical outcome on my machine is 

---------------
$ ruby Singleton.rb
true
"initialize() called by thread #2"
true
"The number of Ups objects is 1"
Singleton.rb:85: private method `new' called for Ups:Class (NoMethodError)


Christoph

---------------
module Singleton
   private
   def Singleton.included(klass)
      class << klass
         def inherited(sub_klass)
            @__instance__ = nil
            def sub_klass.instance
               if defined?(@__allocating__)
                  _wait() until @__instance__
                  return @__instance__
               end
               Thread.critical = true
               unless @__instance__
                  begin
                     @__allocating__ = true
                     Thread.critical = false
                     @__instance__ = new
                     define_method(:instance) {@__instance__ }
                  ensure
                     remove_instance_variable(:@__allocating__)
                  end
               else
                  begin
                     Thread.critical = false
                  ensure
                     remove_instance_variable(:@__allocating__)
                  end
               end
               return @__instance__
            end
         end
         def _load(str)
            instance 
         end
         def _wait()
            sleep(0.05) 
         end 
         private :_load,:_wait, :new, :allocate
      end
      klass.inherited(klass)
   end
   def _dump(depth)
      return "" 
   end 
end 



# simple test
class SomeSingletonClass
   include Singleton
end



a = SomeSingletonClass.instance
b = SomeSingletonClass.instance # a and b are same object
p a == b  # true


# threaded test
class Ups < SomeSingletonClass
   @__threads__=  []
   @@__index__ = nil
   def initialize
      sleep(rand(0.1)/10.0)
      Thread.current[:self]   = self
      Thread.current[:index] = @@__index__  
   end
end
class << Ups
   def initialize_all
       1.upto(4) do |@@__index__|  
         sleep(rand(0.2)/10.0)
         @__threads__.push Thread.new { Thread.current[:instance] = instance }
       end
   end
   def join
      @__threads__.each do |t|
         t.join;
         p "initialize() called by thread ##{t[:index]}" if t[:self]
      end
   end
end

Ups.initialize_all
Ups.join    # only one should be found
p Marshal.load(Marshal.dump(Ups.instance))  == Ups.instance # => true
p "The number of Ups objects is #{ObjectSpace.each_object(Ups) { |obj| }}" 
Ups.new
---------------