--51zEIgjMhjMWwe+h154
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

It still works for me.  See attached.  Diff it perhaps?

-- Markus

On Sat, 2004-10-16 at 08:04, Tassilo Horn wrote:
> Markus <markus / reality.com> writes:
> 
> >      I think (and this  late in a long day for me, so I may be wrong)
> > that the problem is that you are using broadcast to wake the drinkers. 
> > This causes a race condition (as they all assess the table contents "at
> > once") and an eventual deadlock.
> 
> This has come in my mind, too, but...
> 
> >      I tried a quick test of 1) replacing the broadcast with a signal,
> > and 2) adding an else-clause so that the drinker re-signals if what he
> > finds on the table is not what he's wanting.
> 
> ....if I do exactly this it deadlocks even faster.
> 
> >      It makes sense & seems to work, but I'm too pooped to vouch for it
> > beyond that.
> 
> Hm, it makes sense to me, too. But how can it be that it works for you
> but not for me? I use ruby-1.8.2_pre2.
> 
> >      -- Markus
> 
> Thanks and regards,
> 
> Tassilo

--51zEIgjMhjMWwe+h154
Content-Disposition: attachment; filename=waiter
Content-Type: text/plain; name=waiter; charset=UTF-8
Content-Transfer-Encoding: 7bit

#! /usr/bin/env ruby
require 'thread'

# For synchronisation
mutex  utex.new
drinker_cv  onditionVariable.new
waiter_cv  onditionVariable.new

# items on the table:
# 0: cup
# 1: water
# 2: tea
table  ]
items  w{ Cup Water Tea }

# min. 3 drinkers.
if ARGV[0].to_i > 
  drinkers_count  RGV[0].to_i
else
  drinkers_count  
end

drinkers_count.times do |i|
  case i%3
  when 0
    # this drinker has water and tea
    needs  1,2]
  when 1
    # this drinker has a cup and tea
    needs  0,2]
  when 2
    # this drinker has a cup and water
    needs  0,1]
  end
  Thread.new {
    puts "Starting Drinker#{i}"
    while true
      mutex.synchronize {
        drinker_cv.wait(mutex)
        # The things on the table are the things the waiter needs.
        if needs.sort table.sort
          puts "Drinker#{i}: #{items[table[0]]} and #{items[table[1]]} on table. I'll cook my tea!"
          # The Drinker took the items from the table. Now it's empty
          # till the waiter puts new items on it.
          table  ]
          ##sleep 1                                               # (1) #
          puts "Drinker#{i}: Drinking my tea. I call the waiter again."
          # Wake up the waiter Thread
          waiter_cv.signal
          ##sleep 1                                               # (2) #
          puts "Drinker#{i}: Now I'll read my newspaper."
        else
          drinker_cv.signal
        end
    }
      end
  }
end

waiter  hread.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 waiting tea drinkers.
      drinker_cv.signal                                      # (3) #
      puts "WAITER: Waiting for new appointments..."
    waiter_cv.wait(mutex)
  }
    end
}

waiter.join
--51zEIgjMhjMWwe+h154--