Mutex question / request

B

Brian Schroeder

Hello,

playing around with threads I observed, that it is impossible to lock a
mutex twice from within the same thread. Coming from a delphi background
I'm used to have the possibility to enter a critical section as often as I
like, as long as I'm in the same thread. That allows for some simpler
programming, as I can for example allow the user to read from a protected
accessor while he has aquired the lock for some bigger operation.

To be more specific:

The following is not working:
=== Test 1 ===
require 'thread'

m = Mutex.new

m.synchronize do
puts 'locked level 1'
m.synchronize do
puts 'level 2'
end
end
=== EOF ===

I'd like to use it for this usecase:

=== usecase ===
class A
def initialize
@lock = Mutex.new
end

def x
result = ''
@lock.synchronize do
# Do something with result
end
result
end

def synchronize
@lock.synchronize do yield end
end
end

a = A.new
a.synchronize do
# Do something with a
puts a.x
# Do some more with a
end
=== EOF ===

I looked into the thread library and came up with some changes that should
implement the behaviour I want. But my knowledge of ruby threads is quite
limited, so I'd like your feedback on how good this is. Also I'm
interested if you think that this is a good idea, and if it should be
proposed for inclusion in the standard library?

=== MultiMutex ===
class MultiMutex < Mutex
def initialize
@lockingthread = nil
@lockdepth = 0
super
end

def lock
Thread.critical = true
begin
if @lockingthread = Thread.current then
@lockdepth += 1
else
while (Thread.critical = true; @lockdepth > 0)
@waiting.push Thread.current
Thread.stop
end
@lockdepth = 1
end
ensure
Thread.critical = false
end
self
end

def unlock
return @lockdepth unless @locked
Thread.critical = true
begin
if @lockdepth > 1 then
@lockdepth -= 1
return @lockdepth
else
@lockingthread = nil
@lockdepth = 0
begin
t = @waiting.shift
t.wakeup if t
rescue ThreadError
retry
end
end
ensure
Thread.critical = false
end
begin
t.run if t
rescue ThreadError
end
@lockdepth
end
end
=== EOF ===
 
G

Gennady Bystritsky

Hello,

playing around with threads I observed, that it is impossible to lock a
mutex twice from within the same thread. Coming from a delphi
background

Look at monitor.rb (comes in standard Ruby distribution). It has almost
same API as Mutex, however it was designed to be re-enterable by the
current owner.
I'm used to have the possibility to enter a critical section as often
as I
like, as long as I'm in the same thread. That allows for some simpler
programming, as I can for example allow the user to read from a
protected
accessor while he has aquired the lock for some bigger operation.

To be more specific:

The following is not working:
=== Test 1 ===
require 'thread'

m = Mutex.new

m.synchronize do
puts 'locked level 1'
m.synchronize do
puts 'level 2'
end
end
=== EOF ===

I'd like to use it for this usecase:

=== usecase ===
class A
def initialize
@lock = Mutex.new
end

def x
result = ''
@lock.synchronize do
# Do something with result
end
result
end

def synchronize
@lock.synchronize do yield end
end
end

a = A.new
a.synchronize do
# Do something with a
puts a.x
# Do some more with a
end
=== EOF ===

I looked into the thread library and came up with some changes that
should
implement the behaviour I want. But my knowledge of ruby threads is
quite
limited, so I'd like your feedback on how good this is. Also I'm
interested if you think that this is a good idea, and if it should be
proposed for inclusion in the standard library?

=== MultiMutex ===
class MultiMutex < Mutex
def initialize
@lockingthread = nil
@lockdepth = 0
super
end

def lock
Thread.critical = true
begin
if @lockingthread = Thread.current then
@lockdepth += 1
else
while (Thread.critical = true; @lockdepth > 0)
@waiting.push Thread.current
Thread.stop
end
@lockdepth = 1
end
ensure
Thread.critical = false
end
self
end

def unlock
return @lockdepth unless @locked
Thread.critical = true
begin
if @lockdepth > 1 then
@lockdepth -= 1
return @lockdepth
else
@lockingthread = nil
@lockdepth = 0
begin
t = @waiting.shift
t.wakeup if t
rescue ThreadError
retry
end
end
ensure
Thread.critical = false
end
begin
t.run if t
rescue ThreadError
end
@lockdepth
end
end
=== EOF ===

Sincerely,
Gennady Bystritsky
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Mutex 7
Mutex confusion 5
The real difference between Mutex and Sync 7
Thread and Mutex in Ruby 1.8.7 2
Mutex question 2
Thread deadlock 8
thread.rb 11
priority queue using RBTree 2

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top