From: "headius (Charles Nutter)" Date: 2013-09-27T20:35:30+09:00 Subject: [ruby-core:57441] [CommonRuby - Feature #8556] MutexedDelegator as a trivial way to make an object thread-safe Issue #8556 has been updated by headius (Charles Nutter). Similar in nature to the "synchronized" module method proposed in https://bugs.ruby-lang.org/issues/8961. I like that proposal as well, but it does not help the case where you have a concurrency-unsafe object in hand that you would like to make concurrency-safe. Another commenter on Twitter suggested that this is not the best way to go about making an object thread-safe, and he's right. It would be better to use immutable collections or explicitly concurrency-friendly collections. However, this is a simple pattern that works for all types of objects and makes it possible to start writing better threaded Ruby code today. I would also like to note that this is helpful in MRI too, since the bodies of Ruby methods can context switch at any time. MRI also needs a better mechanism for saying "this class's methods should only be executed by one thread at a time". ---------------------------------------- Feature #8556: MutexedDelegator as a trivial way to make an object thread-safe https://bugs.ruby-lang.org/issues/8556#change-42046 Author: headius (Charles Nutter) Status: Open Priority: Normal Assignee: Category: Target version: I propose adding MutexedDelegator as a simple way to wrap any object with a thread-safe wrapper, via existing delegation logic in delegate.rb. Delegator provides a way to pass method calls through to a wrapped object. SimpleDelegator is a trivial implementation that just holds the object in an instance variable. MutexedDelegator would extend SimpleDelegator and only override initialize and 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 mutex.lock target.__send__(m, *args, &block) ensure mutex.unlock end end end The only changes here are: * Mutex#lock and unlock logic wrapping the send * No respond_to? check; I'm not sure why it's there to begin with, since if we're in method_missing the super() call will fail just like a normal 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 calls. -- http://bugs.ruby-lang.org/