diff --git a/lib/thread.rb b/lib/thread.rb index 524db69..cd82682 100644 --- a/lib/thread.rb +++ b/lib/thread.rb @@ -182,16 +182,20 @@ class Queue # def pop(non_block=false) @mutex.synchronize{ - while true - if @que.empty? - raise ThreadError, "queue empty" if non_block - # @waiting.include? check is necessary for avoiding a race against - # Thread.wakeup [Bug 5195] - @waiting.push Thread.current unless @waiting.include?(Thread.current) - @mutex.sleep - else - return @que.shift + begin + while true + if @que.empty? + raise ThreadError, "queue empty" if non_block + # @waiting.include? check is necessary for avoiding a race against + # Thread.wakeup [Bug 5195] + @waiting.push Thread.current unless @waiting.include?(Thread.current) + @mutex.sleep + else + return @que.shift + end end + ensure + @waiting.delete(Thread.current) end } end @@ -298,10 +302,14 @@ class SizedQueue < Queue # def push(obj) @mutex.synchronize{ - while true - break if @que.length < @max - @queue_wait.push Thread.current - @mutex.sleep + begin + while true + break if @que.length < @max + @queue_wait.push Thread.current + @mutex.sleep + end + ensure + @queue_wait.delete(Thread.current) end @que.push obj diff --git a/test/thread/test_queue.rb b/test/thread/test_queue.rb index 685b41a..8ae9422 100644 --- a/test/thread/test_queue.rb +++ b/test/thread/test_queue.rb @@ -53,4 +53,29 @@ class TestQueue < Test::Unit::TestCase assert_raise(ArgumentError) { q.max = -1 } assert_equal(1, q.max) end + + def test_queue_pop_interrupt + q = Queue.new + t1 = Thread.new { q.pop } + sleep 0.01 until t1.stop? + t1.kill.join + assert_equal(0, q.num_waiting) + end + + def test_sized_queue_pop_interrupt + q = SizedQueue.new(1) + t1 = Thread.new { q.pop } + sleep 0.01 until t1.stop? + t1.kill.join + assert_equal(0, q.num_waiting) + end + + def test_sized_queue_push_interrupt + q = SizedQueue.new(1) + q.push(1) + t1 = Thread.new { q.push(2) } + sleep 0.01 until t1.stop? + t1.kill.join + assert_equal(0, q.num_waiting) + end end