|
but the question is, how to write the function coroutine.running() to return the table instead of the corroutine?local coroutine.running()--return ???end2013/7/25 jiang yu <yu.jiang.163@gmail.com>
It can be done by wrap lua's coroutine as a table. and must rewrite coroutine's API.--coroutine poollocal freelist={};function get_freelist()return freelist;endfunction find_free(f)if #freelist > 0 thenlocal free = freelist[#freelist]table.remove(freelist)return {thread = free,func = f,status="create"}endendlocal coroutine_create = coroutine.createlocal coroutine_resume = coroutine.resumelocal coroutine_status = coroutine.status--local coroutine_running = coroutine.runningfunction create_co(f)local tb = {func = f,status="create"}tb.thread = coroutine_create(function (...)local arg = {...}while true doassert(type(arg[1]) == "function",arg[1])arg[1](unpack(arg,2))tb.status = "dead"table.insert(freelist,coroutine.running())arg = {coroutine.yield("co_end")}endend)return tbendfunction coroutine.create(f)return find_free(f) or create_co(f)endfunction coroutine.resume(co,...)if type(co) == "thread" thenreturn coroutine_resume(co,...)endif co.status == "create" thenco.status = "running"return coroutine_resume(co.thread,co.func,...)elseif co.status == "running" thenreturn coroutine_resume(co.thread,...)else --deadprint("error!!! co.status = "..co.status)endendfunction coroutine.status(co)if type(co) == "thread" thenreturn coroutine_status(co)endassert(type(co) == "table")if co.status == "dead" or co.status == "create" thenreturn "dead"endreturn coroutine_status(co.thread)end2013/7/24 jiang yu <yu.jiang.163@gmail.com>
Hi !In my game server there are so many lua's coroutine to make thing easy -- such as instead of state machine. when profile it I find it cost too much memory and cause gc more often. So I want reuse Lua's Coroutine, according to lua gems http://www.lua.org/gems/sample.pdf: I write a file in 200 line(140 for test) to do it.(hope not brother you).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 poollocal freelist={};function get_freelist()return freelist;end
function find_free()if #freelist > 0 thenlocal free = freelist[#freelist]table.remove(freelist)return freeendendCO_TAG = "CO" --for safe use CO_TAGfunction create_co()local co = coroutine.create(function (...)local arg = {...}while true doif 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])elseassert(type(arg[2]) == "function",arg[2])arg[2](unpack(arg,3))table.insert(freelist,coroutine.running())endarg = {coroutine.yield("co_end")}endend)return coendfunction get_free_co()return find_free() or create_co()endfunction wrap(f)local free = get_free_co()return function(...)local isok, msg = coroutine.resume(free,CO_TAG,f,...)if not isok thenprint("CO.wrap error: ", msg)endreturn isok, msgendendfunction run(f,...)local free = get_free_co()return coroutine.resume(free,CO_TAG,f,...)endfunction run_rt_co(f,...)local free = get_free_co()return free,coroutine.resume(free,CO_TAG,f,...)end--testlocal test_co1function 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)endlocal test_co2function 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)endlocal test_co3function 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)endfunction 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)endfunction 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)endfunction 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)endfunction 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)endfunction 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)endtest_error_oldnew()