LCOV - code coverage report
Current view: top level - src - lcorolib.c Coverage Total Hit
Test: Lua 5.3.6 Lines: 89.2 % 83 74
Test Date: 2024-04-28 10:23:15
Legend: Lines: hit not hit

            Line data    Source code
       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         5952 : static lua_State *getco (lua_State *L) {
      22         5952 :   lua_State *co = lua_tothread(L, 1);
      23         5952 :   luaL_argcheck(L, co, 1, "thread expected");
      24         5950 :   return co;
      25              : }
      26              : 
      27              : 
      28         5972 : static int auxresume (lua_State *L, lua_State *co, int narg) {
      29              :   int status;
      30         5972 :   if (!lua_checkstack(co, narg)) {
      31            0 :     lua_pushliteral(L, "too many arguments to resume");
      32            0 :     return -1;  /* error flag */
      33              :   }
      34         5972 :   if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) {
      35            2 :     lua_pushliteral(L, "cannot resume dead coroutine");
      36            2 :     return -1;  /* error flag */
      37              :   }
      38         5970 :   lua_xmove(L, co, narg);
      39         5970 :   status = lua_resume(co, L, narg);
      40         5970 :   if (status == LUA_OK || status == LUA_YIELD) {
      41         5968 :     int nres = lua_gettop(co);
      42         5968 :     if (!lua_checkstack(L, nres + 1)) {
      43            0 :       lua_pop(co, nres);  /* remove results anyway */
      44            0 :       lua_pushliteral(L, "too many results to resume");
      45            0 :       return -1;  /* error flag */
      46              :     }
      47         5968 :     lua_xmove(co, L, nres);  /* move yielded values */
      48         5968 :     return nres;
      49              :   }
      50              :   else {
      51            2 :     lua_xmove(co, L, 1);  /* move error message */
      52            2 :     return -1;  /* error flag */
      53              :   }
      54              : }
      55              : 
      56              : 
      57         5948 : static int luaB_coresume (lua_State *L) {
      58         5948 :   lua_State *co = getco(L);
      59              :   int r;
      60         5947 :   r = auxresume(L, co, lua_gettop(L) - 1);
      61         5947 :   if (r < 0) {
      62            3 :     lua_pushboolean(L, 0);
      63            3 :     lua_insert(L, -2);
      64            3 :     return 2;  /* return false + error message */
      65              :   }
      66              :   else {
      67         5944 :     lua_pushboolean(L, 1);
      68         5944 :     lua_insert(L, -(r + 1));
      69         5944 :     return r + 1;  /* return true + 'resume' returns */
      70              :   }
      71              : }
      72              : 
      73              : 
      74           25 : static int luaB_auxwrap (lua_State *L) {
      75           25 :   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
      76           25 :   int r = auxresume(L, co, lua_gettop(L));
      77           25 :   if (r < 0) {
      78            1 :     if (lua_type(L, -1) == LUA_TSTRING) {  /* error object is a string? */
      79            1 :       luaL_where(L, 1);  /* add extra info */
      80            1 :       lua_insert(L, -2);
      81            1 :       lua_concat(L, 2);
      82              :     }
      83            1 :     return lua_error(L);  /* propagate error */
      84              :   }
      85           24 :   return r;
      86              : }
      87              : 
      88              : 
      89           29 : static int luaB_cocreate (lua_State *L) {
      90              :   lua_State *NL;
      91           29 :   luaL_checktype(L, 1, LUA_TFUNCTION);
      92           27 :   NL = lua_newthread(L);
      93           27 :   lua_pushvalue(L, 1);  /* move function to top */
      94           27 :   lua_xmove(L, NL, 1);  /* move function from L to NL */
      95           27 :   return 1;
      96              : }
      97              : 
      98              : 
      99            8 : static int luaB_cowrap (lua_State *L) {
     100            8 :   luaB_cocreate(L);
     101            7 :   lua_pushcclosure(L, luaB_auxwrap, 1);
     102            7 :   return 1;
     103              : }
     104              : 
     105              : 
     106         5954 : static int luaB_yield (lua_State *L) {
     107         5954 :   return lua_yield(L, lua_gettop(L));
     108              : }
     109              : 
     110              : 
     111            4 : static int luaB_costatus (lua_State *L) {
     112            4 :   lua_State *co = getco(L);
     113            3 :   if (L == co) lua_pushliteral(L, "running");
     114              :   else {
     115            3 :     switch (lua_status(co)) {
     116            1 :       case LUA_YIELD:
     117            1 :         lua_pushliteral(L, "suspended");
     118            1 :         break;
     119            2 :       case LUA_OK: {
     120              :         lua_Debug ar;
     121            2 :         if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
     122            0 :           lua_pushliteral(L, "normal");  /* it is running */
     123            2 :         else if (lua_gettop(co) == 0)
     124            1 :             lua_pushliteral(L, "dead");
     125              :         else
     126            1 :           lua_pushliteral(L, "suspended");  /* initial state */
     127            2 :         break;
     128              :       }
     129            0 :       default:  /* some error occurred */
     130            0 :         lua_pushliteral(L, "dead");
     131            0 :         break;
     132              :     }
     133              :   }
     134            3 :   return 1;
     135              : }
     136              : 
     137              : 
     138            1 : static int luaB_yieldable (lua_State *L) {
     139            1 :   lua_pushboolean(L, lua_isyieldable(L));
     140            1 :   return 1;
     141              : }
     142              : 
     143              : 
     144            1 : static int luaB_corunning (lua_State *L) {
     145            1 :   int ismain = lua_pushthread(L);
     146            1 :   lua_pushboolean(L, ismain);
     147            1 :   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           86 : LUAMOD_API int luaopen_coroutine (lua_State *L) {
     165           86 :   luaL_newlib(L, co_funcs);
     166           86 :   return 1;
     167              : }
     168              : 
        

Generated by: LCOV version 2.0-1