107 lines
3.2 KiB
Lua
107 lines
3.2 KiB
Lua
-- make sure we are pointing to the local copas first
|
|
package.path = string.format("../src/?.lua;%s", package.path)
|
|
|
|
|
|
|
|
local copas = require "copas"
|
|
local Lock = copas.lock
|
|
local gettime = require("socket").gettime
|
|
|
|
local test_complete = false
|
|
copas.loop(function()
|
|
|
|
local lock1 = Lock.new(nil, true) -- not re-entrant
|
|
assert(lock1:get())
|
|
local s = gettime()
|
|
local _, err = lock1:get(1)
|
|
local duration = gettime() - s
|
|
assert(err == "timeout", "got errror: "..tostring(err))
|
|
assert(duration > 1 and duration < 1.2, string.format("expected timeout of 1 second, but took: %f",duration))
|
|
|
|
-- let go and reacquire
|
|
assert(lock1:release())
|
|
local _, err = lock1:release()
|
|
assert(err == "cannot release a lock not owned", "got error: "..tostring(err))
|
|
|
|
assert(lock1:get())
|
|
lock1:destroy()
|
|
local _, err = lock1:release()
|
|
assert(err == "destroyed", "got errror: "..tostring(err))
|
|
|
|
|
|
-- let's scale, go grab a lock
|
|
lock1 = assert(Lock.new(10))
|
|
assert(lock1:get())
|
|
|
|
local success_count = 0
|
|
local timeout_count = 0
|
|
local destroyed_count = 0
|
|
-- now add another bunch of threads for the same lock
|
|
local size = 750 -- must be multiple of 3 !!
|
|
print("creating "..size.." threads hitting the lock...", gettime())
|
|
local tracker = {}
|
|
for i = 1, size do
|
|
tracker[i] = true
|
|
copas.addthread(function()
|
|
local timeout
|
|
if i > (size*2)/3 then
|
|
timeout = 60 -- the ones to hit "destroyed"
|
|
elseif i > size/3 and i <= (size*2)/3 then
|
|
timeout = 2 -- the ones to hit "timeout"
|
|
else
|
|
timeout = 1 -- the ones to succeed
|
|
end
|
|
--print(i, "waiting...")
|
|
local ok, err = lock1:get(timeout)
|
|
if ok then
|
|
--print(i, "got it!")
|
|
success_count = success_count + 1
|
|
if i == size/3 then
|
|
copas.pause(3) -- keep it long enough for the next 500 to timeout
|
|
--print(i, "releasing ")
|
|
assert(lock1:release()) -- by now the 2nd 500 timed out
|
|
--print(i, "destroying ")
|
|
assert(lock1:destroy()) -- make the last 500 fail on "destroyed"
|
|
else
|
|
--print(i, "releasing ")
|
|
assert(lock1:release())
|
|
end
|
|
tracker[i] = nil
|
|
|
|
elseif err == "timeout" then
|
|
--print(i, "timed out!")
|
|
timeout_count = timeout_count + 1
|
|
--if i == (size*2)/3 then
|
|
-- copas.pause(2) -- to ensure thread 500 finished its sleep above
|
|
--end
|
|
tracker[i] = nil
|
|
|
|
elseif err == "destroyed" then
|
|
--print(i, "destroyed!")
|
|
destroyed_count = destroyed_count + 1
|
|
tracker[i] = nil
|
|
|
|
else
|
|
tracker[i] = nil
|
|
error("didn't expect error: '"..tostring(err).."' thread "..i)
|
|
end
|
|
|
|
end) -- added thread function
|
|
end -- for loop
|
|
print("releasing "..size.." threads...", gettime())
|
|
assert(lock1:release())
|
|
print("waiting to finish...")
|
|
while next(tracker) do copas.pause(0.1) end
|
|
-- check results
|
|
print("success: ", success_count)
|
|
print("timeout: ", timeout_count)
|
|
print("destroyed: ", destroyed_count)
|
|
assert(success_count == size/3)
|
|
assert(timeout_count == size/3)
|
|
assert(destroyed_count == size/3)
|
|
|
|
test_complete = true
|
|
end)
|
|
assert(test_complete, "test did not complete!")
|
|
|
|
print("test success!")
|