LCOV - code coverage report
Current view: top level - src - lcorolib.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 88.5 % 78 69
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

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

Generated by: LCOV version 2.0-1