I'm trying to understand how condition variables are supposed to work;
specifically, I've got this code:


# a.rb
require 'monitor'

def try
  a = ""
  a.extend(MonitorMixin)

  cvar = a.new_cond

  t1 = Thread.start do
    a.synchronize do
      cvar.wait
      a << "b"
    end
  end

  t2,t3 = [2,3].map{
    Thread.start do
      a.synchronize do
        a << "a"
        cvar.signal
      end
    end
  }

  [t2,t3,t1].each{|t| t.join}

  return a
end


1000.times do |i|
  output = try()
  raise "Oops! (#{i} says #{output})" unless output == "aba"
end


This consistently fails like this on both jruby-1.5.1 and ruby-1.8.7:

$ ruby a.rb
a.rb:39: Oops! (220 says aab) (RuntimeError)
  from a.rb:37:in `times'
  from a.rb:37

That means that t1 was woken up after both t2 and t3, despite being
signaled to wake up by the first to execute, and it has no indication
that it was signaled twice.

I presume this is intentional behaviour (although it's a *little*
surprising), and the same thing happens if I use Mutex and
ConditionVariable instead of MonitorMixin, so is there any way to ensure
that the thread scheduling goes as [t2,t1,t3] *or* [t3,t1,t2], but never
[t2,t3,t1]?

--
Alex

-- 
Posted via http://www.ruby-forum.com/.