From: Caleb Clausen Date: 2007-06-11T15:32:09+09:00 Subject: Re: Synchronized attr_accessor On 6/10/07, Nasir Khan wrote: > Thanks for the feedback. Here is a refinement - I think there's still a race condition... you need to change this: @@__ms_c_lock.synchronize { @__ms_lock = Mutex.new unless @__ms_lock } unless @__ms_lock To this: @@__ms_c_lock.synchronize { @__ms_lock = Mutex.new unless @__ms_lock unless @__ms_lock } Which is somewhat uglier, since now the class level mutex has to be checked on every synchronized method call. Now, what I had in mind was a little more like this (INCOMPLETELY TESTED): module MethodSynchronizer def MethodSynchronizer.included(into) into.sync_methods.each do |m| MethodSynchronizer.wrap_method(into, m) end end def MethodSynchronizer.wrap_method(klass, meth) klass.class_eval do alias_method "__nonsync_#{meth}", "#{meth}" require 'thread' define_method(:initialize_synchronizer) do @__ms_lock=Mutex.new return self end define_method(meth) do |*args| @__ms_lock.synchronize do self.send("__nonsync_#{meth}",*args) end end end end end And now you have to make sure that #initialize_synchronizer is called on the object before any of the synchronized methods. (What I really was thinking of was hacking into the regular #initialize to get it to do the extra initialization automatically... That can be hairy; among other things, you have to get it into the #initialize of the class being mixed-in to, rather than the module's #initialize. It's not impossible, but it requires more code than I want to write right now.)