1 /* 2 ** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $ 3 ** Coroutine Library 4 ** See Copyright Notice in lua.h 5 */ 6 7 8 #define lcorolib_c 9 #define LUA_LIB 10 11 #include <sys/lua/lua.h> 12 13 #include <sys/lua/lauxlib.h> 14 #include <sys/lua/lualib.h> 15 16 17 static int auxresume (lua_State *L, lua_State *co, int narg) { 18 int status; 19 if (!lua_checkstack(co, narg)) { 20 lua_pushliteral(L, "too many arguments to resume"); 21 return -1; /* error flag */ 22 } 23 if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { 24 lua_pushliteral(L, "cannot resume dead coroutine"); 25 return -1; /* error flag */ 26 } 27 lua_xmove(L, co, narg); 28 status = lua_resume(co, L, narg); 29 if (status == LUA_OK || status == LUA_YIELD) { 30 int nres = lua_gettop(co); 31 if (!lua_checkstack(L, nres + 1)) { 32 lua_pop(co, nres); /* remove results anyway */ 33 lua_pushliteral(L, "too many results to resume"); 34 return -1; /* error flag */ 35 } 36 lua_xmove(co, L, nres); /* move yielded values */ 37 return nres; 38 } 39 else { 40 lua_xmove(co, L, 1); /* move error message */ 41 return -1; /* error flag */ 42 } 43 } 44 45 46 static int luaB_coresume (lua_State *L) { 47 lua_State *co = lua_tothread(L, 1); 48 int r; 49 luaL_argcheck(L, co, 1, "coroutine expected"); 50 r = auxresume(L, co, lua_gettop(L) - 1); 51 if (r < 0) { 52 lua_pushboolean(L, 0); 53 lua_insert(L, -2); 54 return 2; /* return false + error message */ 55 } 56 else { 57 lua_pushboolean(L, 1); 58 lua_insert(L, -(r + 1)); 59 return r + 1; /* return true + 'resume' returns */ 60 } 61 } 62 63 64 static int luaB_auxwrap (lua_State *L) { 65 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 66 int r = auxresume(L, co, lua_gettop(L)); 67 if (r < 0) { 68 if (lua_isstring(L, -1)) { /* error object is a string? */ 69 luaL_where(L, 1); /* add extra info */ 70 lua_insert(L, -2); 71 lua_concat(L, 2); 72 } 73 return lua_error(L); /* propagate error */ 74 } 75 return r; 76 } 77 78 79 static int luaB_cocreate (lua_State *L) { 80 lua_State *NL; 81 luaL_checktype(L, 1, LUA_TFUNCTION); 82 NL = lua_newthread(L); 83 lua_pushvalue(L, 1); /* move function to top */ 84 lua_xmove(L, NL, 1); /* move function from L to NL */ 85 return 1; 86 } 87 88 89 static int luaB_cowrap (lua_State *L) { 90 luaB_cocreate(L); 91 lua_pushcclosure(L, luaB_auxwrap, 1); 92 return 1; 93 } 94 95 96 static int luaB_yield (lua_State *L) { 97 return lua_yield(L, lua_gettop(L)); 98 } 99 100 101 static int luaB_costatus (lua_State *L) { 102 lua_State *co = lua_tothread(L, 1); 103 luaL_argcheck(L, co, 1, "coroutine expected"); 104 if (L == co) lua_pushliteral(L, "running"); 105 else { 106 switch (lua_status(co)) { 107 case LUA_YIELD: 108 lua_pushliteral(L, "suspended"); 109 break; 110 case LUA_OK: { 111 lua_Debug ar; 112 if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ 113 lua_pushliteral(L, "normal"); /* it is running */ 114 else if (lua_gettop(co) == 0) 115 lua_pushliteral(L, "dead"); 116 else 117 lua_pushliteral(L, "suspended"); /* initial state */ 118 break; 119 } 120 default: /* some error occurred */ 121 lua_pushliteral(L, "dead"); 122 break; 123 } 124 } 125 return 1; 126 } 127 128 129 static int luaB_corunning (lua_State *L) { 130 int ismain = lua_pushthread(L); 131 lua_pushboolean(L, ismain); 132 return 2; 133 } 134 135 136 static const luaL_Reg co_funcs[] = { 137 {"create", luaB_cocreate}, 138 {"resume", luaB_coresume}, 139 {"running", luaB_corunning}, 140 {"status", luaB_costatus}, 141 {"wrap", luaB_cowrap}, 142 {"yield", luaB_yield}, 143 {NULL, NULL} 144 }; 145 146 147 148 LUAMOD_API int luaopen_coroutine (lua_State *L) { 149 luaL_newlib(L, co_funcs); 150 return 1; 151 } 152 153 #if defined(_KERNEL) 154 155 EXPORT_SYMBOL(luaopen_coroutine); 156 157 #endif 158