ThreadError: not owner

T

Thomas B.

Hello. I had the following code and it worked in Ruby that came with
some old Windows One-Click Installer (now I don't know which version it
was):

m=Mutex::new
m.lock
Thread:new\
{
# something1
m.unlock
# something2
}
m.synchronize{}

The main thread was supposed to create a new thread, and then wait for
this thread to complete executing something1. But now (RUBY_PATCHLEVEL
#=> 287) the unlock done from the new thread raises ThreadError: not
owner.

OK, that's true that I try to lock and unlock the mutex in two distinct
threads, but is it that bad? Now I need some other way to synchronise
the threads.

I cannot take something1 out of the second thread, because the whole
content of the second thread is in fact wrapped in some begin rescue
clauses, and I don't want to break the scoping, too. The only solution I
can think of now is this:

Thread:new\
{
# something1
Thread.main.wakeup
# something2
}
sleep

But now I risk calling wakeup before the main thread gets to the sleep
command, which will break the whole thing. Of course I could set up some
flag or something...

Are there any better ideas around? Thanks.

TPR.
 
C

Caleb Clausen

Hmmm. I'm guessing that the ability to use a Mutex like a semaphore
wad taken away when the Mutex class was rewritten in c. A Semaphore
class should have then also been added to cover this other use case,
if that ability has to be removed, but I don't see one in my
installation. Signalling is the other important use case for
semaphores besides mutual exclusion. I'd say this is a bug. (But then,
who am I?)

Luckily for you, there's an implementation of Semaphore in ruby here:
http://www.imasy.or.jp/~fukumoto/ruby/semaphore.rb

I can't vouch for that code at all. Note that since it's written in
ruby, it's going to be very slow, compared to the new mutexes... but
then you were using the old (slow) mutexes before so at least you
should be no worse off. Also, Thread.critical is very bad for jruby,
so don't use this there.

You'll have to create a separate variable to hold the semaphore,
something like this: (untested!)

m=Mutex::new
sem=Semaphore.new
Thread.new {
# something1
sem.signal
# something2
}
sem.wait
m.synchronize{}

Maybe you don't even need the mutex at all now. I can't tell from this
little example.
 
T

Thomas B.

Thanks for your responses.

Caleb said:
Hmmm. I'm guessing that the ability to use a Mutex like a semaphore
wad taken away when the Mutex class was rewritten in c. A Semaphore
class should have then also been added to cover this other use case,
if that ability has to be removed, but I don't see one in my
installation. Signalling is the other important use case for
semaphores besides mutual exclusion. I'd say this is a bug. (But then,
who am I?)

That's really strange, I thought there is some mechanism for doing this
and I will get a quick response from somebody who knows it. Also, I
didn't find any info about the change in Mutex functionality anywhere,
and note that the change happened somewhere inside 1.8.6 - my old Ruby
was 1.8.6 and it worked, and my current version is also 1.8.6 (release
date 2008-08-11) and it doesn't.
Luckily for you, there's an implementation of Semaphore in ruby here:
http://www.imasy.or.jp/~fukumoto/ruby/semaphore.rb

Thanks, I'll test it later. In this case I don't need it to be fast,
this is an initialisation and happens not more than several times in the
program. But there is a problem with the example code you provided,
because you do not ensure that the main thread enters the wait state
before the semaphore is signalled.

My current solution is like this:

m=Mutex::new
thr=Thread:new\
{
m.lock
# something1
m.unlock
# something2
}
Thread.pass until m.locked? or not thr.alive?
m.synchronize{}

The initial loop ensures that the second thread locks the mutex before
the main thread does it (by synchronize). I guess it is not perfect, but
it works.

Unfortunately, Monitor does not allow this way of usage, too.

TPR.
 
T

Thomas B.

Thomas said:
But there is a problem with the example code you provided,
because you do not ensure that the main thread enters the wait state
before the semaphore is signalled.

I'm sorry, my mistake. It will work no matter which happens first, as
the semaphore stays signalled even if no thread is currently waiting. My
first glance at the code reported otherwise.

The case I described is really a problem only when using my strange
construction with mutex or sleep.

TPR.
 
C

Caleb Clausen

Thanks for your responses.
[snip]
Unfortunately, Monitor does not allow this way of usage, too.

Really? After I looked into it, it seemed like maybe you could use a
condition variable, but then I've never understood monitors or
condition variables properly. A semaphore seems so much simpler, for
this case, at any rate. I guess condition variables would have the
advantage of being faster, (if they can be made to work) since they
were presumably rendered into c as well.
 
T

Thomas B.

Caleb said:
Thanks for your responses.
[snip]
Unfortunately, Monitor does not allow this way of usage, too.

Really? After I looked into it, it seemed like maybe you could use a
condition variable, but then I've never understood monitors or
condition variables properly. A semaphore seems so much simpler, for
this case, at any rate. I guess condition variables would have the
advantage of being faster, (if they can be made to work) since they
were presumably rendered into c as well.

As far as I know, the only difference between Mutex and Monitor in Ruby
(apart from the internal implementation, I mean) is that Monitors are
reentrant, meaning that a monitor can not only be locked or unlocked,
but it can also be locked multiple times, if all the locks come from the
same thread, so you can do this:
mon.synchronize{mon.synchronize{x}} and get no deadlock or anything. But
still it has to be unlocked by the same thread that locked it.

As for condition variables, I don't think they could help in my
situation. It's not what they are designed for, if I understand them
well. I think that the Semaphore (or maybe I'll write my own Semaphore
class) is the best solution here, only I hoped for a core class for
doing this.
 
B

Brian Candler

Thomas said:
m=Mutex::new
m.lock
Thread:new\
{
# something1
m.unlock
# something2
}
m.synchronize{}

The main thread was supposed to create a new thread, and then wait for
this thread to complete executing something1.

Hmm, so you just need some way for the thread to signal that it has
finished something1? I'd suggest

q = Queue.new
Thread.new do
# something1
q.push:)dummy)
# something2
end
q.pop

The semantics of a queue are very easy to understand :)
 
T

Thomas B.

Brian said:
q = Queue.new
Thread.new do
# something1
q.push:)dummy)
# something2
end
q.pop

Thanks! That seems to be a good solution.

The name Queue is a bit confusing...

TPR.
 
B

Brian Candler

Thomas said:
Thanks! That seems to be a good solution.

The name Queue is a bit confusing...

That's what it is - a first-in, first-out queue. However it is nicely
thread-safe, and the 'pop' operation blocks until there is something to
retrieve, which is what you need here.
 

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

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,619
Members
45,312
Latest member
Svsdvsdvs

Latest Threads

Top