LCOV - code coverage report
Current view: top level - external/lua/src - lcorolib.c (source / functions) Hit Total Coverage
Test: rapport Lines: 3 98 3.1 %
Date: 2021-12-10 16:22:55 Functions: 1 13 7.7 %
Branches: 0 37 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            : ** $Id: lcorolib.c $
       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                 :          0 : static lua_State *getco (lua_State *L) {
      22                 :          0 :   lua_State *co = lua_tothread(L, 1);
      23         [ #  # ]:          0 :   luaL_argexpected(L, co, 1, "thread");
      24                 :          0 :   return co;
      25                 :            : }
      26                 :            : 
      27                 :            : 
      28                 :            : /*
      29                 :            : ** Resumes a coroutine. Returns the number of results for non-error
      30                 :            : ** cases or -1 for errors.
      31                 :            : */
      32                 :          0 : static int auxresume (lua_State *L, lua_State *co, int narg) {
      33                 :            :   int status, nres;
      34         [ #  # ]:          0 :   if (!lua_checkstack(co, narg)) {
      35                 :          0 :     lua_pushliteral(L, "too many arguments to resume");
      36                 :          0 :     return -1;  /* error flag */
      37                 :            :   }
      38                 :          0 :   lua_xmove(L, co, narg);
      39                 :          0 :   status = lua_resume(co, L, narg, &nres);
      40   [ #  #  #  # ]:          0 :   if (status == LUA_OK || status == LUA_YIELD) {
      41         [ #  # ]:          0 :     if (!lua_checkstack(L, nres + 1)) {
      42                 :          0 :       lua_pop(co, nres);  /* remove results anyway */
      43                 :          0 :       lua_pushliteral(L, "too many results to resume");
      44                 :          0 :       return -1;  /* error flag */
      45                 :            :     }
      46                 :          0 :     lua_xmove(co, L, nres);  /* move yielded values */
      47                 :          0 :     return nres;
      48                 :            :   }
      49                 :            :   else {
      50                 :          0 :     lua_xmove(co, L, 1);  /* move error message */
      51                 :          0 :     return -1;  /* error flag */
      52                 :            :   }
      53                 :          0 : }
      54                 :            : 
      55                 :            : 
      56                 :          0 : static int luaB_coresume (lua_State *L) {
      57                 :          0 :   lua_State *co = getco(L);
      58                 :            :   int r;
      59                 :          0 :   r = auxresume(L, co, lua_gettop(L) - 1);
      60         [ #  # ]:          0 :   if (r < 0) {
      61                 :          0 :     lua_pushboolean(L, 0);
      62                 :          0 :     lua_insert(L, -2);
      63                 :          0 :     return 2;  /* return false + error message */
      64                 :            :   }
      65                 :            :   else {
      66                 :          0 :     lua_pushboolean(L, 1);
      67                 :          0 :     lua_insert(L, -(r + 1));
      68                 :          0 :     return r + 1;  /* return true + 'resume' returns */
      69                 :            :   }
      70                 :          0 : }
      71                 :            : 
      72                 :            : 
      73                 :          0 : static int luaB_auxwrap (lua_State *L) {
      74                 :          0 :   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
      75                 :          0 :   int r = auxresume(L, co, lua_gettop(L));
      76         [ #  # ]:          0 :   if (r < 0) {  /* error? */
      77                 :          0 :     int stat = lua_status(co);
      78   [ #  #  #  # ]:          0 :     if (stat != LUA_OK && stat != LUA_YIELD)  /* error in the coroutine? */
      79                 :          0 :       lua_resetthread(co);  /* close its tbc variables */
      80   [ #  #  #  # ]:          0 :     if (stat != LUA_ERRMEM &&  /* not a memory error and ... */
      81                 :          0 :         lua_type(L, -1) == LUA_TSTRING) {  /* ... error object is a string? */
      82                 :          0 :       luaL_where(L, 1);  /* add extra info, if available */
      83                 :          0 :       lua_insert(L, -2);
      84                 :          0 :       lua_concat(L, 2);
      85                 :          0 :     }
      86                 :          0 :     return lua_error(L);  /* propagate error */
      87                 :            :   }
      88                 :          0 :   return r;
      89                 :          0 : }
      90                 :            : 
      91                 :            : 
      92                 :          0 : static int luaB_cocreate (lua_State *L) {
      93                 :            :   lua_State *NL;
      94                 :          0 :   luaL_checktype(L, 1, LUA_TFUNCTION);
      95                 :          0 :   NL = lua_newthread(L);
      96                 :          0 :   lua_pushvalue(L, 1);  /* move function to top */
      97                 :          0 :   lua_xmove(L, NL, 1);  /* move function from L to NL */
      98                 :          0 :   return 1;
      99                 :            : }
     100                 :            : 
     101                 :            : 
     102                 :          0 : static int luaB_cowrap (lua_State *L) {
     103                 :          0 :   luaB_cocreate(L);
     104                 :          0 :   lua_pushcclosure(L, luaB_auxwrap, 1);
     105                 :          0 :   return 1;
     106                 :            : }
     107                 :            : 
     108                 :            : 
     109                 :          0 : static int luaB_yield (lua_State *L) {
     110                 :          0 :   return lua_yield(L, lua_gettop(L));
     111                 :            : }
     112                 :            : 
     113                 :            : 
     114                 :            : #define COS_RUN         0
     115                 :            : #define COS_DEAD        1
     116                 :            : #define COS_YIELD       2
     117                 :            : #define COS_NORM        3
     118                 :            : 
     119                 :            : 
     120                 :            : static const char *const statname[] =
     121                 :            :   {"running", "dead", "suspended", "normal"};
     122                 :            : 
     123                 :            : 
     124                 :          0 : static int auxstatus (lua_State *L, lua_State *co) {
     125         [ #  # ]:          0 :   if (L == co) return COS_RUN;
     126                 :            :   else {
     127      [ #  #  # ]:          0 :     switch (lua_status(co)) {
     128                 :            :       case LUA_YIELD:
     129                 :          0 :         return COS_YIELD;
     130                 :            :       case LUA_OK: {
     131                 :            :         lua_Debug ar;
     132         [ #  # ]:          0 :         if (lua_getstack(co, 0, &ar))  /* does it have frames? */
     133                 :          0 :           return COS_NORM;  /* it is running */
     134         [ #  # ]:          0 :         else if (lua_gettop(co) == 0)
     135                 :          0 :             return COS_DEAD;
     136                 :            :         else
     137                 :          0 :           return COS_YIELD;  /* initial state */
     138                 :            :       }
     139                 :            :       default:  /* some error occurred */
     140                 :          0 :         return COS_DEAD;
     141                 :            :     }
     142                 :            :   }
     143                 :          0 : }
     144                 :            : 
     145                 :            : 
     146                 :          0 : static int luaB_costatus (lua_State *L) {
     147                 :          0 :   lua_State *co = getco(L);
     148                 :          0 :   lua_pushstring(L, statname[auxstatus(L, co)]);
     149                 :          0 :   return 1;
     150                 :            : }
     151                 :            : 
     152                 :            : 
     153                 :          0 : static int luaB_yieldable (lua_State *L) {
     154         [ #  # ]:          0 :   lua_State *co = lua_isnone(L, 1) ? L : getco(L);
     155                 :          0 :   lua_pushboolean(L, lua_isyieldable(co));
     156                 :          0 :   return 1;
     157                 :            : }
     158                 :            : 
     159                 :            : 
     160                 :          0 : static int luaB_corunning (lua_State *L) {
     161                 :          0 :   int ismain = lua_pushthread(L);
     162                 :          0 :   lua_pushboolean(L, ismain);
     163                 :          0 :   return 2;
     164                 :            : }
     165                 :            : 
     166                 :            : 
     167                 :          0 : static int luaB_close (lua_State *L) {
     168                 :          0 :   lua_State *co = getco(L);
     169                 :          0 :   int status = auxstatus(L, co);
     170         [ #  # ]:          0 :   switch (status) {
     171                 :            :     case COS_DEAD: case COS_YIELD: {
     172                 :          0 :       status = lua_resetthread(co);
     173         [ #  # ]:          0 :       if (status == LUA_OK) {
     174                 :          0 :         lua_pushboolean(L, 1);
     175                 :          0 :         return 1;
     176                 :            :       }
     177                 :            :       else {
     178                 :          0 :         lua_pushboolean(L, 0);
     179                 :          0 :         lua_xmove(co, L, 1);  /* copy error message */
     180                 :          0 :         return 2;
     181                 :            :       }
     182                 :            :     }
     183                 :            :     default:  /* normal or running coroutine */
     184                 :          0 :       return luaL_error(L, "cannot close a %s coroutine", statname[status]);
     185                 :            :   }
     186                 :          0 : }
     187                 :            : 
     188                 :            : 
     189                 :            : static const luaL_Reg co_funcs[] = {
     190                 :            :   {"create", luaB_cocreate},
     191                 :            :   {"resume", luaB_coresume},
     192                 :            :   {"running", luaB_corunning},
     193                 :            :   {"status", luaB_costatus},
     194                 :            :   {"wrap", luaB_cowrap},
     195                 :            :   {"yield", luaB_yield},
     196                 :            :   {"isyieldable", luaB_yieldable},
     197                 :            :   {"close", luaB_close},
     198                 :            :   {NULL, NULL}
     199                 :            : };
     200                 :            : 
     201                 :            : 
     202                 :            : 
     203                 :        810 : LUAMOD_API int luaopen_coroutine (lua_State *L) {
     204                 :        810 :   luaL_newlib(L, co_funcs);
     205                 :        810 :   return 1;
     206                 :            : }
     207                 :            : 

Generated by: LCOV version 1.15