Project

General

Profile

Feature #8556

Updated by nobu (Nobuyoshi Nakada) over 6 years ago

=begin 
 I propose adding (({MutexedDelegator})) MutexedDelegator as a simple way to wrap any object with a thread-safe wrapper, via existing delegation logic in ((%delegate.rb%)). delegate.rb. 

 (({Delegator})) Delegator provides a way to pass method calls through to a wrapped object. (({SimpleDelegator})) SimpleDelegator is a trivial implementation that just holds the object in an instance variable. (({MutexedDelegator})) MutexedDelegator would extend (({SimpleDelegator})) SimpleDelegator and only override initialize and (({method_missing})) method_missing as follows: 

   

 class MutexedDelegator < SimpleDelegator 
     
   def initialize(*) 
       
     super 
       
     @mutex = Mutex.new 
     
   end 
    
     
  
   def method_missing(m, *args, &block) 
       
     target, mutex = self.__getobj__, @mutex 
     begin 
       begin 
         mutex.lock 
         
       target.__send__(m, *args, &block) 
     ensure 
       ensure 
         mutex.unlock 
       end 
     end 
   end 
 end 

 The only changes here are: 

 * (({Mutex#lock})) Mutex#lock and (({unlock})) unlock logic wrapping the send 
 * No (({respond_to?})) respond_to? check; I'm not sure why it's there to begin with, since if we're in (({method_missing})) method_missing the (({super()})) super() call will fail just like a normal (({method_missing})) method_missing failure anyway 
 * No backtrace manipulation. This does not work on JRuby and Rubinius anyway, and in this case I feel that the delegator should not hide itself, since there's real behavior change happening. 

 This is a trivial addition to stdlib that would make it simple to synchronize all calls to a given object in the same way as the JDK's (({Collections.synchronizedSet}))/(({Map}))/(({List})) Collections.synchronizedSet/Map/List calls. 
 =end 

Back