Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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