I am using a Mutex to protect a function, but I need to call into the
function again from the same thread without deadlocking:
class A
def initialize @m = Mutex.new
end
def a @m.synchronize { b }
end
def b @m.synchronize { puts “hello” }
end
end
A.new.a #-> deadlock
It seems to me that to achieve this, all i need to do is track which thread
has the mutex locked, and allow access if the same thread requests it again:
class Mutex2
def initialize @m = Mutex.new @l = nil
end
def synchronize
if @l == Thread.current
yield
else @m.synchronize { @l = Thread.current
begin
yield
ensure @l = nil
end
}
end
end
end
q1) am i reinventing the wheel and/or making it square?
q2) is this safe?
You may want to use monitor.rb instead (from the standard ruby
distribution), it is designed to be reentrant, while Mutex is not.
Gennady.
Martin Hart wrote:
···
Hi all,
I am using a Mutex to protect a function, but I need to call into the
function again from the same thread without deadlocking:
class A
def initialize @m = Mutex.new
end
def a @m.synchronize { b }
end
def b @m.synchronize { puts “hello” }
end
end
A.new.a #-> deadlock
It seems to me that to achieve this, all i need to do is track which thread
has the mutex locked, and allow access if the same thread requests it again:
class Mutex2
def initialize @m = Mutex.new @l = nil
end
def synchronize
if @l == Thread.current
yield
else @m.synchronize { @l = Thread.current
begin
yield
ensure @l = nil
end
}
end
end
end
q1) am i reinventing the wheel and/or making it square?
q2) is this safe?
It misleads users into thinking Mutex is more useful than it
is, and they eventually get caught (like the original poster
and myself).
good point - although in my case it’s not so much not knowing that they
exist as being intimidated by the source code
Granted in this instance I suppose it’s not that difficult to fathom what is
going on - but just compare the easy to understand comments & code for in
thread.rb with the code + hardly any useful comments in sync.rb (ruby 1.8).
That was enough to put me off looking any further (although now as it
happens I am using sync.rb).
On the positive side - it’s a great testament to the design of Ruby and its
included libraries that all I had to do was change one line, and my entire
system now uses Sync instead of Mutex
Why is Mutex even mentioned at all? Ruby comes with a
Ferrari and a Yugo – and we’re telling them to use the Yugo.
Presumably there is a performance penalty to pay to gain the extra features
provided by Sync and its ilk? If not, then I’m 100% in agreement.