1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
require "spec"
require "../support/fibers"
describe Mutex do
it "locks and unlocks" do
mutex = Mutex.new
mutex.lock
mutex.unlock
end
it "works with multiple threads" do
x = 0
mutex = Mutex.new
fibers = 10.times.map do
spawn do
100.times do
mutex.synchronize { x += 1 }
end
end
end.to_a
fibers.each do |f|
wait_until_finished f
end
x.should eq(1000)
end
describe "checked" do
it "raises if locked recursively" do
mutex = Mutex.new
mutex.lock
expect_raises(Exception, "Attempt to lock a mutex recursively (deadlock)") do
mutex.lock
end
end
it "raises if unlocks without lock" do
mutex = Mutex.new
expect_raises(Exception, "Attempt to unlock a mutex which is not locked") do
mutex.unlock
end
end
it "can't be unlocked by another fiber" do
mutex = nil
done = false
spawn do
mutex = Mutex.new
mutex.not_nil!.lock
done = true
end
until done
Fiber.yield
end
expect_raises(Exception, "Attempt to unlock a mutex locked by another fiber") do
mutex.not_nil!.unlock
end
end
end
describe "reentrant" do
it "can be locked many times from the same fiber" do
mutex = Mutex.new(:reentrant)
mutex.lock
mutex.lock
mutex.unlock
mutex.unlock
end
it "raises if unlocks without lock" do
mutex = Mutex.new(:reentrant)
expect_raises(Exception, "Attempt to unlock a mutex which is not locked") do
mutex.unlock
end
end
it "can't be unlocked by another fiber" do
mutex = nil
done = false
spawn do
mutex = Mutex.new(:reentrant)
mutex.not_nil!.lock
done = true
end
until done
Fiber.yield
end
expect_raises(Exception, "Attempt to unlock a mutex locked by another fiber") do
mutex.not_nil!.unlock
end
end
end
describe "unchecked" do
it "can lock and unlock from multiple fibers" do
mutex = Mutex.new(:unchecked)
a = 1
two = false
three = false
four = false
ch = Channel(Nil).new
spawn do
mutex.synchronize do
a = 2
Fiber.yield
two = a == 2
end
ch.send(nil)
end
spawn do
mutex.synchronize do
a = 3
Fiber.yield
three = a == 3
end
ch.send(nil)
end
spawn do
mutex.synchronize do
a = 4
Fiber.yield
four = a == 4
end
ch.send(nil)
end
3.times { ch.receive }
two.should be_true
three.should be_true
four.should be_true
end
end
end
|