> This discussion has made me wonder if there is
> some "generic" way of handling serializing in
> druby.
>
> Wouldn't it be nice if you could simply mix in
> a module, like
>
>   myobj.extend(ThreadSafe)
>
> and then start the service normally and forget it?


I always use MonitorMixin.

require 'monitor'

class MyClass
   include MonitorMixin
   ...
   def initialize
     super
     ...
   end

   def foo
     synchronize do
       ...
     end
   end
end



Do you want to call synchronize automatically?
How is a thing like Delegator ?


require 'monitor'

class SyncDelegator
   include MonitorMixin

   def initialize(obj)
     super()
     preserved = ::Kernel.instance_methods
     preserved -= ["to_s","to_a","inspect","==","=~","==="]
     for t in self.type.ancestors
       preserved |= t.instance_methods
       preserved |= t.private_instance_methods
       preserved |= t.protected_instance_methods
       break if t == SyncDelegator
     end
     for method in obj.methods
       next if preserved.include? method
       eval <<-EOS
	def self.#{method}(*args, &block)
	  begin
	    synchronize do
	      __getobj__.__send__(:#{method}, *args, &block)
             end
	  rescue Exception
	    $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
	    $@.delete_if{|s| /^\\(eval\\):/ =~ s}
	    raise
	  end
	end
       EOS
     end
   end

   def __getobj__
     raise NotImplementError, "need to define `__getobj__'"
   end

end

class SimpleSyncDelegator<SyncDelegator

   def initialize(obj)
     super
     @obj = obj
   end

   def __getobj__
     @obj
   end

   def __setobj__(obj)
     @obj = obj
   end
end



if __FILE__ == $0
   class Slow
     def do_it
       p [:do_it, Time.now]
       sleep 2
       p [:done]
     end
   end

   if true
     # sync
     slow = Slow.new
     $slow = SimpleSyncDelegator.new(slow)
   else
     # don't sync
     $slow = Slow.new
   end

   t1 = Thread.new do
     5.times do
       $slow.do_it
     end
   end

   t2 = Thread.new do
     5.times do
       $slow.do_it
     end
   end

   t1.join
   t2.join
end