the question is, the test can not pass the test_error_oldnew(), the situation is: test1 create a coroutine and run it, the pool find it end and give the coroutine to test2, but the test1 not realise it end and resume it again.
I know it is a bug that should not happen,but may be happen. in the normal lua case, it is not dangerous just get a error and easily detect, but under coroutine pool it is very dangerous and can not detect. how to deal with it?
--coroutine pool
local freelist={};
function get_freelist()
return freelist;
end
function find_free()
if #freelist > 0 then
local free = freelist[#freelist]
table.remove(freelist)
return free
end
end
CO_TAG = "CO" --for safe use CO_TAG
function create_co()
local co = coroutine.create(
function (...)
local arg = {...}
while true do
if arg[1] ~= CO_TAG then
--do nothing, but can not error(...) because the co is in freelist. but how to let caller know it?
print("error! arg[1] ~= CO_TAG",arg[1])
else
assert(type(arg[2]) == "function",arg[2])
arg[2](unpack(arg,3))
table.insert(freelist,coroutine.running())
end
arg = {coroutine.yield("co_end")}
end
end)
return co
end
function get_free_co()
return find_free() or create_co()
end
function wrap(f)
local free = get_free_co()
return function(...)
local isok, msg = coroutine.resume(free,CO_TAG,f,...)
if not isok then
print("CO.wrap error: ", msg)
end
return isok, msg
end
end
function run(f,...)
local free = get_free_co()
return coroutine.resume(free,CO_TAG,f,...)
end
function run_rt_co(f,...)
local free = get_free_co()
return free,coroutine.resume(free,CO_TAG,f,...)
end
--test
local test_co1
function t1(p1)
test_co1 = coroutine.running()
print("inco t1 1",p1)
local rt = coroutine.yield("t1 y1")
assert(rt == "r1")
print("inco t1 end",rt)
end
local test_co2
function t2(p1,p2)
test_co2 = coroutine.running()
print("inco t2 1",p1,p2)
local rt = coroutine.yield("t2 y2")
assert(rt == "r2")
print("inco t2 2",rt)
rt = coroutine.yield("t2 y2")
assert(rt == "r2")
print("inco t2 end",rt)
end
local test_co3
function t3(p1,p2)
test_co3 = coroutine.running()
print("inco t3 1",p1,p2)
local rt = coroutine.yield("t3 y3")
assert(rt == "r3")
error("inco t3")
rt = coroutine.yield("t3 y3")
assert(rt == "r3")
print("inco t3 end",rt)
end
function test()
print("#freelist",#freelist)
assert(#freelist == 0)
local ok,rt = run(t1,"p1")
print('run(t1,"p1")',ok,rt)
ok,rt = coroutine.resume(test_co1,"r1")
print('coroutine.resume(test_co1,"r1")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
ok,rt = run(t2,"p1","p2")
assert(test_co1 == test_co2)
--print("freelist",#freelist)
print('run(t2,"p1","p2")',ok,rt)
ok,rt = coroutine.resume(test_co2,"r2")
print('coroutine.resume(test_co2,"r2")',ok,rt)
ok,rt = coroutine.resume(test_co2,"r2")
print('coroutine.resume(test_co2,"r2")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
end
function test_wrap()
print("#freelist",#freelist)
assert(#freelist == 0)
local f1 = wrap(t1)
local ok,rt = f1("p1")
print('f1("p1")',ok,rt)
ok,rt = coroutine.resume(test_co1,"r1")
print('coroutine.resume(test_co1,"r1")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
local f2 = wrap(t2)
ok,rt = f2("p1","p2")
assert(test_co1 == test_co2)
--print("freelist",#freelist)
print('f2("p1","p2")',ok,rt)
ok,rt = coroutine.resume(test_co2,"r2")
print('coroutine.resume(test_co2,"r2")',ok,rt)
ok,rt = coroutine.resume(test_co2,"r2")
print('coroutine.resume(test_co2,"r2")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
end
function test_error()
print("#freelist",#freelist)
assert(#freelist == 0)
local f3 = wrap(t3)
print("local f3 = wrap(t3)")
ok,rt = f3("p1","p2")
print('f3("p1","p2")',ok,rt)
ok,rt = coroutine.resume(test_co3,"r3")
print('coroutine.resume(test_co3,"r3")',ok,rt)
ok,rt = coroutine.resume(test_co3,"r3")
print('coroutine.resume(test_co3,"r3")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 0)
end
function test_error_tag()
print("#freelist",#freelist)
assert(#freelist == 0)
local f1 = wrap(t1)
local ok,rt = f1("p1")
print('f1("p1")',ok,rt)
ok,rt = coroutine.resume(test_co1,"r1")
print('coroutine.resume(test_co1,"r1")',ok,rt)
assert(#freelist == 1)
ok,rt = coroutine.resume(test_co1,"r1") --CO_TAG will used here!
print('coroutine.resume(test_co1,"r1")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
end
function test_error_oldnew()
print("#freelist",#freelist)
assert(#freelist == 0)
local f1 = wrap(t1)
local ok,rt = f1("p1")
print('f1("p1")',ok,rt)
ok,rt = coroutine.resume(test_co1,"r1")
print('coroutine.resume(test_co1,"r1")',ok,rt)
print("#freelist",#freelist)
assert(#freelist == 1)
local f2 = wrap(t2)
print("local f2 = wrap(t2)")
ok,rt = f2("p1","p2")
assert(test_co1 == test_co2)
print("freelist",#freelist)
assert(#freelist == 0)
print('f2("p1","p2")',ok,rt)
ok,rt = coroutine.resume(test_co2,"r2")
print('coroutine.resume(test_co2,"r2")',ok,rt)
ok,rt = coroutine.resume(test_co1,"r1")
print('coroutine.resume(test_co1,"r1")',ok,rt)
print("#freelist",#freelist)
end
test_error_oldnew()