Mutex re-entrancy

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?

TIA
Martin

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?

TIA
Martin

See [ruby-talk:84293].

class A
include MonitorMixin

def a
  synchronize { b }
end

def b
  synchronize { puts "hello" }
end

end

Paul

···

On Fri, May 28, 2004 at 01:47:31AM +0900, 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:

Also take a look at sync.rb:

require ‘sync’

class A
def initialize
@m = Sync.new
end

def a
  @m.synchronize { b }
end

def b
  @m.synchronize { puts "hello" }
end

end

Paul

I once I went through the same ordeal as the original poster,
until someone told me to look at sync.rb.

It made me wonder why pickaxe devotes a whole page to Mutex
and then, in one short sentence at the end, mentions sync.rb
and monitor.rb.

It misleads users into thinking Mutex is more useful than it
is, and they eventually get caught (like the original poster
and myself).

Why is Mutex even mentioned at all? Ruby comes with a
Ferrari and a Yugo – and we’re telling them to use the Yugo.

···

— Paul Brannan pbrannan@atdesk.com wrote:

Also take a look at sync.rb:


Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around

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 :slight_smile:

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 :slight_smile:

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.

Cheers,
Martin

···

----- Original Message -----
From: “Jeff Mitchell” quixoticsycophant@yahoo.com