Feature #8556
Updated by nobu (Nobuyoshi Nakada) about 11 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