SHARE
TWEET

Untitled




Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
- class QueueWithTimeout
- def initialize
- @mutex = Mutex.new
- @queue = []
- @recieved = ConditionVariable.new
- end
- def <<(x)
- @mutex.synchronize do
- @queue << x
- @recieved.signal
- puts "Signalled"
- end
- end
- def pop(non_block = false)
- pop_with_timeout(non_block ? 0 : nil)
- end
- def pop_with_timeout(timeout = nil)
- printf "pop_with_timeout in #{Thread.current[:id]}\n"
- @mutex.synchronize do
- if @queue.empty?
- puts "Queue empty in #{Thread.current[:id]}"
- @recieved.wait(@mutex, timeout) if timeout != 0
- puts "Resuming in #{Thread.current[:id]}"
- #if we're still empty after the timeout, raise exception
- raise ThreadError, "queue empty" if @queue.empty?
- end
- @queue.shift
- end
- end
- end
- queue = QueueWithTimeout.new
- Thread.abort_on_exception = true
- 10.times do |i|
- Thread.new do
- Thread.current[:id] = i
- loop do
- queue.pop_with_timeout(100000.0) # a long timeout, that we'll never reach
- puts i
- end
- end
- end
- loop do
- queue << "random stuff"
- puts "pushed"
- end
- __END__
- # Example program output (comments on the right after the # char)
- $ ruby condition_variable_signal.rb
- pop_with_timeout in 2
- Queue empty in 2
- pop_with_timeout in 0
- pop_with_timeout in 1
- Signalled # @recieved.signal called, note that other threads run before condition_variable is actually resumed on line 75
- pop_with_timeout in 9
- pop_with_timeout in 4
- pop_with_timeout in 5
- pop_with_timeout in 6
- pop_with_timeout in 7
- pop_with_timeout in 8
- pop_with_timeout in 3
- pushed
- 0 # Thread 0 popped the value. Note that thread 0 never called @recieved.wait(...)!
- pop_with_timeout in 0
- Resuming in 2 # Thread 2 wakes up and finds empty queue.
- Queue empty in 1
- Queue empty in 9
- Queue empty in 4
- condition_variable_signal.rb:28:in `block in pop_with_timeout': queue empty (ThreadError)
- from condition_variable_signal.rb:22:in `synchronize'
- from condition_variable_signal.rb:22:in `pop_with_timeout'
- from condition_variable_signal.rb:43:in `block (3 levels) in <main>'
- from condition_variable_signal.rb:42:in `loop'
- from condition_variable_signal.rb:42:in `block (2 levels) in <main>'
- Conclusions
- - I couldn't reproduce "spurious wakeup" behavior.
- - I was able to find/reproduce a bug related to interesting `ConditionVariable#signal` behavior, see program output with comments above.
- - I do agree using `while` loop with a condition variable predicate solves the problem.
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy.