lua coroutine & skynet

来源:互联网 发布:淘宝店粉丝怎么看 编辑:程序博客网 时间:2024/05/21 06:33

1.lua中的协程

thread type

用于创建协程(coroutines),跟OS的thread不是一个概念

Python则不同,Python的线程就是OS原生线程;不过stackless和pypy的微线程跟这个概念差不多

Coroutines

又名collaborative multithreading(协作多线程)

每个协程是一个独立的线程(lua thread, not os thread),当前协程只有在显式调用yield时才会挂起

coroutine.create(..)创建协程,参数:协程要执行的main函数;返回值:thread对象,指向协程

coroutine.resume(..)启动/恢复协程,第一个参数是thread对象

启动时其他参数传递给协程对应的main函数

恢复时其他参数赋值给中断时yield赋值的对象

coroutine.yield(..)挂起协程,导致coroutine.resume()立即返回,返回值:true+yield的参数;

下次resume时从这个点恢复执行

The next time you resume the same coroutine, it continues its execution from the point where it yielded, with the call to coroutine.yield returning any extra arguments passed to coroutine.resume.

coroutine.wrap(..)创建协程,参数:协程要执行的main函数;返回值:function,调用function则等效于coroutine.resume(..),参数被传递给协程main函数

跟cotoutine.resume(..)的主要区别是不捕获错误,错误会向上传播,返回值没有第一个boolean.

其实说白了就是对main函数做了一个包装,不用显示的调用resume,可以差不多像原函数一样使用

协程结束:

1.协程执行的函数终结,这种情况coroutine.resume()返回true+协程函数返回值

2.协程执行的函数出现无保护的错误,这种情况coroutine.resume()返回false+错误信息

EXAMPLE:

[dongsong@localhost skynet]$ luaLua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio> =coroutinetable: 0x113f600> for k,v in pairs(coroutine) do print(k,v) endresume  function: 0x113f830yield   function: 0x113f9b0status  function: 0x113f8f0wrap    function: 0x113f950create  function: 0x113e2e0running function: 0x113f890

[dongsong@localhost lua-study]$ cat coroutine.lua function foo (a)print("foo", a)return coroutine.yield(2*a)                 --resume returned: true 4endco = coroutine.create(function (a,b)print("co-body", a, b)local r = foo(a+1)print("co-body", r)local r, s = coroutine.yield(a+b, a-b)      --resume returned: true 11 -9print("co-body", r, s)return b, "end"                             --resume returned: true 10 endend)print("main", coroutine.resume(co, 1, 10))      --main true 4print("main", coroutine.resume(co, "r"))        --main true 11 -9print("main", coroutine.resume(co, "x", "y"))   --main true 10 endprint("main", coroutine.resume(co, "x", "y"))   --main false cannot resume dead coroutine[dongsong@localhost lua-study]$ [dongsong@localhost lua-study]$ lua coroutine.lua co-body 1       10foo     2main    true    4co-body rmain    true    11      -9co-body x       ymain    true    10      endmain    false   cannot resume dead coroutine

2.skynet对协程的改造过程:说白了,把lua默认的coroutine.resume和coroutine.yield作为upvalue打进了DIY的lresume和lyield,并把协程启动时间和累计运行时间作为upvalue打进lstart/lstop/lresume/lyield

int  luaopen_profile(lua_State *L) {          luaL_checkversion(L);          luaL_Reg l[] = {                  { "start", lstart },                  { "stop", lstop },                  { "resume", lresume },                  { "yield", lyield },                  { NULL, NULL },          };          luaL_newlibtable(L,l);          lua_newtable(L);        // table thread->start time          lua_newtable(L);        // table thread->total time      /*  *  table -> total time  *  table -> start time  *  table -> libtable     */            lua_newtable(L);        // weak table          lua_pushliteral(L, "kv");          lua_setfield(L, -2, "__mode");      /*  *  table -> weak table  *  table -> total time  *  table -> start time  *  table -> libtable     */            lua_pushvalue(L, -1);          lua_setmetatable(L, -3);           lua_setmetatable(L, -3);      /*  *  table -> total time with weak metatable  *  table -> start time with weak metatable  *  table -> libtable     */            lua_pushnil(L);          luaL_setfuncs(L,l,3);      /*  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lresume/lyield: table->starttime, table->totaltime, nil      */            int libtable = lua_gettop(L); //libtable = 1            lua_getglobal(L, "coroutine"); //获取lua默认的coroutine库          lua_getfield(L, -1, "resume"); //获取lua默认的coroutine.resume函数            lua_CFunction co_resume = lua_tocfunction(L, -1); //co_resume=lua默认的coroutine.resume函数          if (co_resume == NULL)                  return luaL_error(L, "Can't get coroutine.resume");          lua_pop(L,1); //把lua默认的coroutine.resume从stack中弹出去      /*  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lresume/lyield: table->starttime, table->totaltime, nil      */          lua_getfield(L, libtable, "resume");      /*  *  cfunction lresume  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lresume/lyield: table->starttime, table->totaltime, nil      */          lua_pushcfunction(L, co_resume);      /*  *  cfunction co_resume (lua default coroutine.resume)  *  cfunction lresume  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lresume/lyield: table->starttime, table->totaltime, nil      */          lua_setupvalue(L, -2, 3);      /*  *  cfunction lresume with upvalues: table->starttime, table->totaltime, co_resume (coroutine.resume)  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lyield: table->starttime, table->totaltime, nil   *           upvalues of lresume: table->starttime, table->totaltime, co_resume (coroutine.resume)      */          lua_pop(L,1);      /*  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lyield: table->starttime, table->totaltime, nil   *           upvalues of lresume: table->starttime, table->totaltime, co_resume (coroutine.resume)      */            lua_getfield(L, -1, "yield");            lua_CFunction co_yield = lua_tocfunction(L, -1); //co_yield=coroutine.yield          if (co_yield == NULL)                  return luaL_error(L, "Can't get coroutine.yield");          lua_pop(L,1);      /*  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop/lyield: table->starttime, table->totaltime, nil   *           upvalues of lresume: table->starttime, table->totaltime, co_resume (coroutine.resume)      */          lua_getfield(L, libtable, "yield");          lua_pushcfunction(L, co_yield);          lua_setupvalue(L, -2, 3);      /*  *  cfunction lyield with upvalues: table->starttime, table->totaltime, co_yield (coroutine.yield)  *  coroutine (lua coroutine table)  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop: table->starttime, table->totaltime, nil   *           upvalues of lresume: table->starttime, table->totaltime, co_resume (coroutine.resume)   *           upvalues of lyield: table->starttime, table->totaltime, co_yield (coroutine.yield)      */            lua_settop(L, libtable);      /*  *  table -> libtable: {start=lstart, stop=lstop, resume=lresume, yield=lyield};   *           upvalues of lstart/lstop: table->starttime, table->totaltime, nil   *           upvalues of lresume: table->starttime, table->totaltime, co_resume (coroutine.resume)   *           upvalues of lyield: table->starttime, table->totaltime, co_yield (coroutine.yield)      */            return 1;  }


0 0
原创粉丝点击