From: Adam Bender Date: 2008-03-26T07:32:27+09:00 Subject: Re: thread.rb On Tue, Mar 25, 2008 at 2:01 PM, MenTaLguY wrote: > I do agree that the following thread.rb operations need to directly > support timeouts, though: > > ConditionVariable#wait ConditionVariable#wait appears to support timeouts (http://www.ruby-doc.org/stdlib/libdoc/monitor/rdoc/classes/MonitorMixin/ConditionVariable.html#M001018). Do they not work as expected? I couldn't find the Scheduler gem, so I'm trying to hack something together based your code example, but using Monitors. It depends on ConditionVariable#wait, so it could be totally broken. I didn't understand the point of the Reader class in your code, since only one thread at a time can acquire the lock in pop. This problem is closely related to the example on page 146 of Pickaxe 2nd ed. require 'monitor' class MyQueue def initialize @values = [] @values.extend(MonitorMixin) @cond = @values.new_cond end def push(value) @values.synchronize do @values.push value @cond.signal end self end def pop(timeout=nil) ret = nil @values.synchronize do t = Time.now @cond.wait(timeout) puts "waited #{Time.now - t}" ret = @values.shift unless @values.empty? end return ret end end q = MyQueue.new consumers = (1..3).map do |i| Thread.new("consumer #{i}") do |name| begin obj = q.pop(5) puts "#{name} consumed #{obj.inspect}" sleep(rand(0.05)) end until obj == :END_OF_WORK end end producers = (1..3).map do |i| Thread.new("producer #{i}") do |name| 3.times do |j| sleep(1) q.push("Item #{j} from #{name}") end end end producers.each { |th| th.join } consumers.size.times { q.push(:END_OF_WORK) } consumers.each { |th| th.join } The problem is that the wait() waits for timeout seconds, even when something is in the queue. Thanks for your help, Adam