Issue #8556 has been updated by headius (Charles Nutter).


I implemented this and a simple test in https://github.com/ruby/ruby/pull/405

If approved, I can merge that or commit to trunk directly.

The performance impact of Monitor is a separate issue; Monitor should probably be implemented natively to get maximum performance. I'm considering doing that for JRuby as well. As you point out, reentrancy is needed for any code that might call out to a block which might call back in.

There's not a great deal we can do to speed up Monitor as it is currently written, but perhaps you could file a bug for that and we can see about improving things.
----------------------------------------
Feature #8556: MutexedDelegator as a trivial way to make an object thread-safe
https://bugs.ruby-lang.org/issues/8556#change-42117

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: Ruby 2.1.0


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/