?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

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