Move common lock test behavior out of mutex spec into module.
This commit is contained in:
parent
2af2cdc852
commit
5dc3c7299e
|
@ -0,0 +1,60 @@
|
||||||
|
module ProcessShared
|
||||||
|
# Classes that include this module should assign a lock object to
|
||||||
|
# @lock before each test.
|
||||||
|
module LockBehavior
|
||||||
|
|
||||||
|
# Fork +n+ processes. In each, yield the block (passing the process
|
||||||
|
# number), then call Kernel.exit! Waits for all processes to
|
||||||
|
# complete before returning.
|
||||||
|
def fork_many(n)
|
||||||
|
pids = []
|
||||||
|
n.times do |i|
|
||||||
|
pids << fork do
|
||||||
|
yield i
|
||||||
|
Kernel.exit!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pids.each { |pid| ::Process.wait(pid) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_protects_access_to_a_shared_variable
|
||||||
|
mem = SharedMemory.new(:char)
|
||||||
|
mem.put_char(0, 0)
|
||||||
|
|
||||||
|
fork_many(10) do |i|
|
||||||
|
inc = (-1) ** i # half the procs increment; half decrement
|
||||||
|
10.times do
|
||||||
|
@lock.lock
|
||||||
|
begin
|
||||||
|
mem.put_char(0, mem.get_char(0) + inc)
|
||||||
|
sleep 0.001
|
||||||
|
ensure
|
||||||
|
@lock.unlock
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mem.get_char(0).must_equal(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_protects_access_to_a_shared_variable_with_synchronize
|
||||||
|
mem = SharedMemory.new(:char)
|
||||||
|
mem.put_char(0, 0)
|
||||||
|
|
||||||
|
fork_many(10) do |i|
|
||||||
|
inc = (-1) ** i # half the procs increment; half decrement
|
||||||
|
10.times do
|
||||||
|
@lock.synchronize do
|
||||||
|
mem.put_char(0, mem.get_char(0) + inc)
|
||||||
|
sleep 0.001
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mem.get_char(0).must_equal(0)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,81 +1,35 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
require 'process_shared'
|
require 'process_shared'
|
||||||
|
|
||||||
|
require 'process_shared/lock_behavior'
|
||||||
|
|
||||||
module ProcessShared
|
module ProcessShared
|
||||||
describe Mutex do
|
describe Mutex do
|
||||||
it 'protects access to a shared variable' do
|
|
||||||
mutex = Mutex.new
|
|
||||||
mem = SharedMemory.new(:char)
|
|
||||||
mem.put_char(0, 0)
|
|
||||||
|
|
||||||
pids = []
|
include LockBehavior
|
||||||
10.times do |i|
|
|
||||||
inc = (-1) ** i # half the procs increment; half decrement
|
|
||||||
pids << fork do
|
|
||||||
10.times do
|
|
||||||
mutex.lock
|
|
||||||
begin
|
|
||||||
mem.put_char(0, mem.get_char(0) + inc)
|
|
||||||
sleep 0.001
|
|
||||||
ensure
|
|
||||||
mutex.unlock
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Kernel.exit!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
pids.each { |pid| ::Process.wait(pid) }
|
before :each do
|
||||||
|
@lock = Mutex.new
|
||||||
mem.get_char(0).must_equal(0)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'protects access to a shared variable with synchronize' do
|
|
||||||
mutex = Mutex.new
|
|
||||||
mem = SharedMemory.new(:char)
|
|
||||||
mem.put_char(0, 0)
|
|
||||||
|
|
||||||
pids = []
|
|
||||||
10.times do |i|
|
|
||||||
inc = (-1) ** i # half the procs increment; half decrement
|
|
||||||
pids << fork do
|
|
||||||
10.times do
|
|
||||||
mutex.synchronize do
|
|
||||||
mem.put_char(0, mem.get_char(0) + inc)
|
|
||||||
sleep 0.001
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Kernel.exit!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
pids.each { |pid| ::Process.wait(pid) }
|
|
||||||
|
|
||||||
mem.get_char(0).must_equal(0)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'raises exception when unlocked by other process' do
|
it 'raises exception when unlocked by other process' do
|
||||||
mutex = Mutex.new
|
|
||||||
|
|
||||||
pid = Kernel.fork do
|
pid = Kernel.fork do
|
||||||
mutex.lock
|
@lock.lock
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
mutex.unlock
|
@lock.unlock
|
||||||
Kernel.exit!
|
Kernel.exit!
|
||||||
end
|
end
|
||||||
|
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
proc { mutex.unlock }.must_raise(ProcessError)
|
proc { @lock.unlock }.must_raise(ProcessError)
|
||||||
|
|
||||||
::Process.wait(pid)
|
::Process.wait(pid)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises exception when locked twice by same process' do
|
it 'raises exception when locked twice by same process' do
|
||||||
mutex = Mutex.new
|
@lock.lock
|
||||||
|
proc { @lock.lock }.must_raise(ProcessError)
|
||||||
mutex.lock
|
@lock.unlock
|
||||||
proc { mutex.lock }.must_raise(ProcessError)
|
|
||||||
mutex.unlock
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue