1require "monitor" 2require "thread" 3 4require "test/unit" 5 6class TestMonitor < Test::Unit::TestCase 7 def setup 8 @monitor = Monitor.new 9 end 10 11 def test_enter 12 ary = [] 13 queue = Queue.new 14 th = Thread.start { 15 queue.pop 16 @monitor.enter 17 for i in 6 .. 10 18 ary.push(i) 19 Thread.pass 20 end 21 @monitor.exit 22 } 23 @monitor.enter 24 queue.enq(nil) 25 for i in 1 .. 5 26 ary.push(i) 27 Thread.pass 28 end 29 @monitor.exit 30 th.join 31 assert_equal((1..10).to_a, ary) 32 end 33 34 def test_synchronize 35 ary = [] 36 queue = Queue.new 37 th = Thread.start { 38 queue.pop 39 @monitor.synchronize do 40 for i in 6 .. 10 41 ary.push(i) 42 Thread.pass 43 end 44 end 45 } 46 @monitor.synchronize do 47 queue.enq(nil) 48 for i in 1 .. 5 49 ary.push(i) 50 Thread.pass 51 end 52 end 53 th.join 54 assert_equal((1..10).to_a, ary) 55 end 56 57 def test_killed_thread_in_synchronize 58 ary = [] 59 queue = Queue.new 60 t1 = Thread.start { 61 queue.pop 62 @monitor.synchronize { 63 ary << :t1 64 } 65 } 66 t2 = Thread.start { 67 queue.pop 68 @monitor.synchronize { 69 ary << :t2 70 } 71 } 72 @monitor.synchronize do 73 queue.enq(nil) 74 queue.enq(nil) 75 assert_equal([], ary) 76 t1.kill 77 t2.kill 78 ary << :main 79 end 80 assert_equal([:main], ary) 81 end 82 83 def test_try_enter 84 queue1 = Queue.new 85 queue2 = Queue.new 86 th = Thread.start { 87 queue1.deq 88 @monitor.enter 89 queue2.enq(nil) 90 queue1.deq 91 @monitor.exit 92 queue2.enq(nil) 93 } 94 assert_equal(true, @monitor.try_enter) 95 @monitor.exit 96 queue1.enq(nil) 97 queue2.deq 98 assert_equal(false, @monitor.try_enter) 99 queue1.enq(nil) 100 queue2.deq 101 assert_equal(true, @monitor.try_enter) 102 end 103 104 def test_cond 105 cond = @monitor.new_cond 106 107 a = "foo" 108 queue1 = Queue.new 109 Thread.start do 110 queue1.deq 111 @monitor.synchronize do 112 a = "bar" 113 cond.signal 114 end 115 end 116 @monitor.synchronize do 117 queue1.enq(nil) 118 assert_equal("foo", a) 119 result1 = cond.wait 120 assert_equal(true, result1) 121 assert_equal("bar", a) 122 end 123 end 124 125 def test_timedwait 126 cond = @monitor.new_cond 127 b = "foo" 128 queue2 = Queue.new 129 Thread.start do 130 queue2.deq 131 @monitor.synchronize do 132 b = "bar" 133 cond.signal 134 end 135 end 136 @monitor.synchronize do 137 queue2.enq(nil) 138 assert_equal("foo", b) 139 result2 = cond.wait(0.1) 140 assert_equal(true, result2) 141 assert_equal("bar", b) 142 end 143 144 c = "foo" 145 queue3 = Queue.new 146 Thread.start do 147 queue3.deq 148 @monitor.synchronize do 149 c = "bar" 150 cond.signal 151 end 152 end 153 @monitor.synchronize do 154 assert_equal("foo", c) 155 result3 = cond.wait(0.1) 156 assert_equal(true, result3) # wait always returns true in Ruby 1.9 157 assert_equal("foo", c) 158 queue3.enq(nil) 159 result4 = cond.wait 160 assert_equal(true, result4) 161 assert_equal("bar", c) 162 end 163 164# d = "foo" 165# cumber_thread = Thread.start { 166# loop do 167# @monitor.synchronize do 168# d = "foo" 169# end 170# end 171# } 172# queue3 = Queue.new 173# Thread.start do 174# queue3.pop 175# @monitor.synchronize do 176# d = "bar" 177# cond.signal 178# end 179# end 180# @monitor.synchronize do 181# queue3.enq(nil) 182# assert_equal("foo", d) 183# result5 = cond.wait 184# assert_equal(true, result5) 185# # this thread has priority over cumber_thread 186# assert_equal("bar", d) 187# end 188# cumber_thread.kill 189 end 190end 191