[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Problems with my first multithreaded Rupy programm

Tassilo Horn

10/8/2004 3:13:00 PM

Hi,

I'm trying to get into Ruby and today it's time for
multithreading. Therefore I wanted to write a program which does this:

In a tearoom there are three thirsty drinkers. To cook a tea one
needs water, tea and a cup. Every one of these three drinkers
has one of those items with him.
Every time the waiter is called he puts two items on the
table. Now one drinker has all the items he needs and cooks his
tea. After that he calls the waiter and the fun begins again...

Ok, here's what I wrote so far and what produces this output:

,----
| (%:~/tmp/Teadrinker)- ./TeaRoom.rb
| WAITER: Looking at the table!
| WAITER: Oh, nothing on the table!
| WAITER: Putting 1 and 2 on the table.
| deadlock 0x4023b798: sleep:J(0x4022603c) (main) - ./TeaRoom.rb:94
| deadlock 0x40225e70: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
| deadlock 0x40225efc: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
| deadlock 0x40225f88: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
| deadlock 0x4022603c: sleep:- - ./TeaRoom.rb:31
| ./TeaRoom.rb:31: Thread(0x4022603c): deadlock (fatal)
`----

<----- CODE ----->

#! /usr/bin/env ruby

require 'thread'

# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new

# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

waiter = Thread.new {
while true
mutex.synchronize {
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
sleep 2
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
$stdout << "WAITER: Putting " << table[0] << " and " << table[1]
<< " on the table.\n"
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
cv.broadcast
Thread.stop
}
end
}

# Mike has a cup (0)
mike = Thread.new {
while true
mutex.synchronize {
cv.wait(mutex)
if table.include?(1) and table.include?(2)
puts "MIKE: Water and tea on table. I'll cook my tea."
table = []
sleep 3
puts "MIKE: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter.wakeup
sleep 3
puts "MIKE: Now I will read my newspaper."
else
puts "MIKE: Not what I need."
end
}
end
}

# Al has water (1)
al = Thread.new {
while true
mutex.synchronize {
cv.wait(mutex)
if table.include?(0) and table.include?(2)
puts "AL: Cup and tea on table. I'll cook my tea."
table = []
sleep 3
puts "AL: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter.wakeup
sleep 3
puts "AL: Now I will read my newspaper."
else
puts "AL: Not what I need."
end
}
end
}

# Ed has tea (2)
ed = Thread.new {
while true
mutex.synchronize {
cv.wait(mutex)
if table.include?(0) and table.include?(1)
puts "ED: Cup and water on table. I'll cook my tea."
table = []
sleep 3
puts "ED: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter.wakeup
sleep 3
puts "ED: Now I will read my newspaper."
else
puts "ED: Not what I need."
end
}
end
}

waiter.join

<----- END OF CODE ----->

What's wrong with these lines?

Much thanks in advance,
Tassilo
10 Answers

Markus

10/8/2004 3:55:00 PM

0

Try taking the cv.broadcast and the Thread.stop out of the mutex
syncronize block (e.g., let go before you tell the others to start).

-- Markus


On Fri, 2004-10-08 at 08:14, Tassilo Horn wrote:
> Hi,
>
> I'm trying to get into Ruby and today it's time for
> multithreading. Therefore I wanted to write a program which does this:
>
> In a tearoom there are three thirsty drinkers. To cook a tea one
> needs water, tea and a cup. Every one of these three drinkers
> has one of those items with him.
> Every time the waiter is called he puts two items on the
> table. Now one drinker has all the items he needs and cooks his
> tea. After that he calls the waiter and the fun begins again...
>
> Ok, here's what I wrote so far and what produces this output:
>
> ,----
> | (%:~/tmp/Teadrinker)- ./TeaRoom.rb
> | WAITER: Looking at the table!
> | WAITER: Oh, nothing on the table!
> | WAITER: Putting 1 and 2 on the table.
> | deadlock 0x4023b798: sleep:J(0x4022603c) (main) - ./TeaRoom.rb:94
> | deadlock 0x40225e70: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
> | deadlock 0x40225efc: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
> | deadlock 0x40225f88: sleep:- - /usr/lib/ruby/1.8/thread.rb:96
> | deadlock 0x4022603c: sleep:- - ./TeaRoom.rb:31
> | ./TeaRoom.rb:31: Thread(0x4022603c): deadlock (fatal)
> `----
>
> <----- CODE ----->
>
> #! /usr/bin/env ruby
>
> require 'thread'
>
> # For synchronisation
> mutex = Mutex.new
> cv = ConditionVariable.new
>
> # items on the table:
> # 0: cup
> # 1: water
> # 2: tea
> table = []
>
> waiter = Thread.new {
> while true
> mutex.synchronize {
> puts "WAITER: Looking at the table!"
> if table.length == 0
> puts "WAITER: Oh, nothing on the table!"
> sleep 2
> while table[0] == table[1] do
> table = [rand(3), rand(3)]
> end
> $stdout << "WAITER: Putting " << table[0] << " and " << table[1]
> << " on the table.\n"
> else
> puts "WAITER: Why did you call me???"
> end
> # Call the waiting tea drinkers
> cv.broadcast
> Thread.stop
> }
> end
> }
>
> # Mike has a cup (0)
> mike = Thread.new {
> while true
> mutex.synchronize {
> cv.wait(mutex)
> if table.include?(1) and table.include?(2)
> puts "MIKE: Water and tea on table. I'll cook my tea."
> table = []
> sleep 3
> puts "MIKE: Drinking my tea. Calling the waiter."
> # Wake up the waiter-Thread
> waiter.wakeup
> sleep 3
> puts "MIKE: Now I will read my newspaper."
> else
> puts "MIKE: Not what I need."
> end
> }
> end
> }
>
> # Al has water (1)
> al = Thread.new {
> while true
> mutex.synchronize {
> cv.wait(mutex)
> if table.include?(0) and table.include?(2)
> puts "AL: Cup and tea on table. I'll cook my tea."
> table = []
> sleep 3
> puts "AL: Drinking my tea. Calling the waiter."
> # Wake up the waiter-Thread
> waiter.wakeup
> sleep 3
> puts "AL: Now I will read my newspaper."
> else
> puts "AL: Not what I need."
> end
> }
> end
> }
>
> # Ed has tea (2)
> ed = Thread.new {
> while true
> mutex.synchronize {
> cv.wait(mutex)
> if table.include?(0) and table.include?(1)
> puts "ED: Cup and water on table. I'll cook my tea."
> table = []
> sleep 3
> puts "ED: Drinking my tea. Calling the waiter."
> # Wake up the waiter-Thread
> waiter.wakeup
> sleep 3
> puts "ED: Now I will read my newspaper."
> else
> puts "ED: Not what I need."
> end
> }
> end
> }
>
> waiter.join
>
> <----- END OF CODE ----->
>
> What's wrong with these lines?
>
> Much thanks in advance,
> Tassilo



Sean Russell

10/8/2004 4:43:00 PM

0

A couple of things.

1) Create the Waiter last. He's got the lock on the mutex, so none of
the other threads can enter their synchronized sections, so they can't
wait. They're simply blocking while waiting to enter the protected
section. It doesn't matter that the waiter is sleep()ing, because he
still has the lock. If you create the waiter last, then everybody else
has a chance to enter a synchronized section and wait (releasing the
lock) before the waiter does his thing.

2) Don't use Thread.stop. It isn't doing what I think you think it is
doing.

3) Create another CV just for the waiter, so you can send signals
directly to him

4) Wrap your "whiles" in the synchronized sections, not the other way
around. For one thing, entering synchronized sections are costly; you
want to do it as rarely as you can. For another, when you wait(), you
release the lock, allowing others to get at the lock, so it is OK to
put the while inside the synchronized section.

5) If I was going to clean up the code for you, I'd recommend doing
something like this:

Here's a version that works:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'


# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new


# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

# Mike has a cup (0)
mike = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(1) and table.include?(2)
puts "MIKE: Water and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "MIKE: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "MIKE: Now I will read my newspaper."
else
puts "MIKE: Not what I need."
end
end
}

}

# Al has water (1)
al = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(2)
puts "AL: Cup and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "AL: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "AL: Now I will read my newspaper."
else
puts "AL: Not what I need."
end
end
}
}

# Ed has tea (2)
ed = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(1)
puts "ED: Cup and water on table. I'll cook my tea."
table = []
#sleep 3
puts "ED: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "ED: Now I will read my newspaper."
else
puts "ED: Not what I need."
end
end
}
}

waiter = Thread.new {
mutex.synchronize {
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
#sleep 2
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
$stdout << "WAITER: Putting " << table[0] << " and " <<
table[1] << " on the table.\n"
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
}
}

waiter.join
</code>


And here's a cleaner, shorter version:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'

# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new


# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

items = %w{ Cup Water Tea }
[ [:Mike,1,2], [:Al,0,2], [:Ed,0,1] ].each do |guy, *needs|
Thread.new do
puts "Doing #{guy}"
mutex.synchronize do
while true
cv.wait(mutex)
if (table & needs).size == 2
puts "#{guy}: #{items[table[0]]} and #{items[table[1]]} on
table. "+
"I'll cook my tea."
table = []
puts "#{guy}: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
puts "#{guy}: Now I will read my newspaper."
else
puts "#{guy}: Not what I need."
end
end
end
end
end

waiter = Thread.new do
mutex.synchronize do
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
puts "WAITER: Putting #{items[table[0]]} and #{items[table[1]]}
on the table."
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
end
end

waiter.join
</code>

--- SER

Sean Russell

10/8/2004 4:43:00 PM

0

A couple of things.

1) Create the Waiter last. He's got the lock on the mutex, so none of
the other threads can enter their synchronized sections, so they can't
wait. They're simply blocking while waiting to enter the protected
section. It doesn't matter that the waiter is sleep()ing, because he
still has the lock. If you create the waiter last, then everybody else
has a chance to enter a synchronized section and wait (releasing the
lock) before the waiter does his thing.

2) Don't use Thread.stop. It isn't doing what I think you think it is
doing.

3) Create another CV just for the waiter, so you can send signals
directly to him

4) Wrap your "whiles" in the synchronized sections, not the other way
around. For one thing, entering synchronized sections are costly; you
want to do it as rarely as you can. For another, when you wait(), you
release the lock, allowing others to get at the lock, so it is OK to
put the while inside the synchronized section.

5) If I was going to clean up the code for you, I'd recommend doing
something like this:

Here's a version that works:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'


# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new


# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

# Mike has a cup (0)
mike = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(1) and table.include?(2)
puts "MIKE: Water and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "MIKE: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "MIKE: Now I will read my newspaper."
else
puts "MIKE: Not what I need."
end
end
}

}

# Al has water (1)
al = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(2)
puts "AL: Cup and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "AL: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "AL: Now I will read my newspaper."
else
puts "AL: Not what I need."
end
end
}
}

# Ed has tea (2)
ed = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(1)
puts "ED: Cup and water on table. I'll cook my tea."
table = []
#sleep 3
puts "ED: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "ED: Now I will read my newspaper."
else
puts "ED: Not what I need."
end
end
}
}

waiter = Thread.new {
mutex.synchronize {
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
#sleep 2
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
$stdout << "WAITER: Putting " << table[0] << " and " <<
table[1] << " on the table.\n"
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
}
}

waiter.join
</code>


And here's a cleaner, shorter version:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'

# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new


# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

items = %w{ Cup Water Tea }
[ [:Mike,1,2], [:Al,0,2], [:Ed,0,1] ].each do |guy, *needs|
Thread.new do
puts "Doing #{guy}"
mutex.synchronize do
while true
cv.wait(mutex)
if (table & needs).size == 2
puts "#{guy}: #{items[table[0]]} and #{items[table[1]]} on
table. "+
"I'll cook my tea."
table = []
puts "#{guy}: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
puts "#{guy}: Now I will read my newspaper."
else
puts "#{guy}: Not what I need."
end
end
end
end
end

waiter = Thread.new do
mutex.synchronize do
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
puts "WAITER: Putting #{items[table[0]]} and #{items[table[1]]}
on the table."
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
end
end

waiter.join
</code>

--- SER

Tassilo Horn

10/8/2004 4:44:00 PM

0

Markus <markus@reality.com> writes:

> Try taking the cv.broadcast and the Thread.stop out of the mutex
> syncronize block (e.g., let go before you tell the others to start).

But then the waiter puts two item on the table but no drinker takes them
away.

The output is then:

,----
| WAITER: Looking at the table!
| WAITER: Oh, nothing on the table!
| WAITER: Putting 0 and 1 on the table.
| WAITER: Looking at the table!
| WAITER: Why did you call me???
| WAITER: Looking at the table!
| WAITER: Why did you call me???
| ...
`----

But it should work like this:

The waiter puts two items on the table and falls asleep.
The drinker who needs those two items wakes up, consumes them,
drinks his tea and wakes up the waiter.
The waiter puts two new items on the table.
The drinker who needs those two items wakes up, ...

I hope I didn't understand you wrong.

Regards,
Tassilo

Sean Russell

10/8/2004 4:44:00 PM

0

A couple of things.

1) Create the Waiter last. He's got the lock on the mutex, so none of
the other threads can enter their synchronized sections, so they can't
wait. They're simply blocking while waiting to enter the protected
section. It doesn't matter that the waiter is sleep()ing, because he
still has the lock. If you create the waiter last, then everybody else
has a chance to enter a synchronized section and wait (releasing the
lock) before the waiter does his thing.

2) Don't use Thread.stop. It isn't doing what I think you think it is
doing.

3) Create another CV just for the waiter, so you can send signals
directly to him

4) Wrap your "whiles" in the synchronized sections, not the other way
around. For one thing, entering synchronized sections are costly; you
want to do it as rarely as you can. For another, when you wait(), you
release the lock, allowing others to get at the lock, so it is OK to
put the while inside the synchronized section.

5) If I was going to clean up the code for you, I'd recommend doing
something like this:

Here's a version that works:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'

# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new

# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

# Mike has a cup (0)
mike = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(1) and table.include?(2)
puts "MIKE: Water and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "MIKE: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "MIKE: Now I will read my newspaper."
else
puts "MIKE: Not what I need."
end
end
}
}

# Al has water (1)
al = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(2)
puts "AL: Cup and tea on table. I'll cook my tea."
table = []
#sleep 3
puts "AL: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "AL: Now I will read my newspaper."
else
puts "AL: Not what I need."
end
end
}
}

# Ed has tea (2)
ed = Thread.new {
mutex.synchronize {
while true
cv.wait(mutex)
if table.include?(0) and table.include?(1)
puts "ED: Cup and water on table. I'll cook my tea."
table = []
#sleep 3
puts "ED: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
#sleep 3
puts "ED: Now I will read my newspaper."
else
puts "ED: Not what I need."
end
end
}
}

waiter = Thread.new {
mutex.synchronize {
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
#sleep 2
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
$stdout << "WAITER: Putting " << table[0] << " and " <<
table[1] << " on the table.\n"
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
}
}

waiter.join
</code>


And here's a cleaner, shorter version:

<code lang='ruby'>
#!/usr/bin/env ruby

require 'thread'

# For synchronisation
mutex = Mutex.new
cv = ConditionVariable.new
waiter_cv = ConditionVariable.new


# items on the table:
# 0: cup
# 1: water
# 2: tea
table = []

items = %w{ Cup Water Tea }
[ [:Mike,1,2], [:Al,0,2], [:Ed,0,1] ].each do |guy, *needs|
Thread.new do
puts "Doing #{guy}"
mutex.synchronize do
while true
cv.wait(mutex)
if (table & needs).size == 2
puts "#{guy}: #{items[table[0]]} and #{items[table[1]]} on
table. "+
"I'll cook my tea."
table = []
puts "#{guy}: Drinking my tea. Calling the waiter."
# Wake up the waiter-Thread
waiter_cv.signal
puts "#{guy}: Now I will read my newspaper."
else
puts "#{guy}: Not what I need."
end
end
end
end
end

waiter = Thread.new do
mutex.synchronize do
while true
puts "#"*80
puts "WAITER: Looking at the table!"
if table.length == 0
puts "WAITER: Oh, nothing on the table!"
while table[0] == table[1] do
table = [rand(3), rand(3)]
end
puts "WAITER: Putting #{items[table[0]]} and #{items[table[1]]}
on the table."
else
puts "WAITER: Why did you call me???"
end
# Call the waiting tea drinkers
puts "WAITER: Broadcast"
cv.broadcast
puts "WAITER: Wait"
waiter_cv.wait(mutex)
end
end
end

waiter.join
</code>

--- SER

Sean Russell

10/8/2004 4:47:00 PM

0

Wow. Google groups really screws up the formatting of code. Sorry
about that. I hope you have a good editor that'll re-indent code for
you.

--- SER

Tassilo Horn

10/8/2004 5:02:00 PM

0

"SER" <ser@germane-software.com> writes:

> A couple of things.

Perfect. I'm willing to learn.

> 1) Create the Waiter last. He's got the lock on the mutex, so none of
> the other threads can enter their synchronized sections, so they can't
> wait. They're simply blocking while waiting to enter the protected
> section. It doesn't matter that the waiter is sleep()ing, because he
> still has the lock. If you create the waiter last, then everybody else
> has a chance to enter a synchronized section and wait (releasing the
> lock) before the waiter does his thing.

Ah, I understand.

> 2) Don't use Thread.stop. It isn't doing what I think you think it is
> doing.

I was quite sure it's not doing what I wanted it to do but had no better
idea how to do what I want it to do. ;-)

> 3) Create another CV just for the waiter, so you can send signals
> directly to him

And that is the solution for 2) which I didn't realize.

> 4) Wrap your "whiles" in the synchronized sections, not the other way
> around. For one thing, entering synchronized sections are costly; you
> want to do it as rarely as you can. For another, when you wait(), you
> release the lock, allowing others to get at the lock, so it is OK to
> put the while inside the synchronized section.

Ok.

> 5) If I was going to clean up the code for you, I'd recommend doing
> something like this:

Oh, thanks. I hope I'll be disciplinated enough to first implementing
your tips on my own before reading you code...

Much thanks for your great help. But _one_ posting would have been
enough! ;-)

Regards,
Tassilo

Markus

10/8/2004 5:04:00 PM

0

On Fri, 2004-10-08 at 09:44, Tassilo Horn wrote:
> Markus <markus@reality.com> writes:
>
> > Try taking the cv.broadcast and the Thread.stop out of the mutex
> > syncronize block (e.g., let go before you tell the others to start).
>
> But then the waiter puts two item on the table but no drinker takes them
> away.
>
> I hope I didn't understand you wrong.
>

I fear you might have; I didn't mean to eliminate them, simply to
move them down to right after the '}' instead of right before it. It
seemed to work for me (I just tried it).

-- Markus



Tassilo Horn

10/8/2004 5:42:00 PM

0

Markus <markus@reality.com> writes:

> I fear you might have; I didn't mean to eliminate them, simply to
> move them down to right after the '}' instead of right before it. It
> seemed to work for me (I just tried it).

Ah, that's ok. But there were other things skewed up in my code. I
refactored my code obeying SER's tips and now it works like a charm.

But thanks for your fast reply.

Regards,
Tassilo
--
The sticker on the side of the box said "Supported Platforms: Windows 95,
Windows NT 4.0, or better", so clearly Linux was a supported platform.

Sean Russell

10/8/2004 7:43:00 PM

0

> Much thanks for your great help. But _one_ posting would have been
> enough! ;-)

Google Groups (beta). I try to not complain too much, since it is a
free service, but it is the only way I have of reading usenet from
behind a firewall, and in addition to really munging posts, it often
returns server errors while trying to post. Since the errors are
always varied and new, when they look really bad, I resubmit the post.
That's what happened here.

Google Groups (nonbeta) is even worse, in that posting can take six
hours to propegate to usenet.

Sorry about that.

--- SER