lcorolib.c
Go to the documentation of this file.
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 static lua_State *getco (lua_State *L) {
22  lua_State *co = lua_tothread(L, 1);
23  luaL_argexpected(L, co, 1, "thread");
24  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 static int auxresume (lua_State *L, lua_State *co, int narg) {
33  int status, nres;
34  if (l_unlikely(!lua_checkstack(co, narg))) {
35  lua_pushliteral(L, "too many arguments to resume");
36  return -1; /* error flag */
37  }
38  lua_xmove(L, co, narg);
39  status = lua_resume(co, L, narg, &nres);
40  if (l_likely(status == LUA_OK || status == LUA_YIELD)) {
41  if (l_unlikely(!lua_checkstack(L, nres + 1))) {
42  lua_pop(co, nres); /* remove results anyway */
43  lua_pushliteral(L, "too many results to resume");
44  return -1; /* error flag */
45  }
46  lua_xmove(co, L, nres); /* move yielded values */
47  return nres;
48  }
49  else {
50  lua_xmove(co, L, 1); /* move error message */
51  return -1; /* error flag */
52  }
53 }
54 
55 
56 static int luaB_coresume (lua_State *L) {
57  lua_State *co = getco(L);
58  int r;
59  r = auxresume(L, co, lua_gettop(L) - 1);
60  if (l_unlikely(r < 0)) {
61  lua_pushboolean(L, 0);
62  lua_insert(L, -2);
63  return 2; /* return false + error message */
64  }
65  else {
66  lua_pushboolean(L, 1);
67  lua_insert(L, -(r + 1));
68  return r + 1; /* return true + 'resume' returns */
69  }
70 }
71 
72 
73 static int luaB_auxwrap (lua_State *L) {
75  int r = auxresume(L, co, lua_gettop(L));
76  if (l_unlikely(r < 0)) { /* error? */
77  int stat = lua_status(co);
78  if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
79  stat = lua_resetthread(co); /* close its tbc variables */
80  lua_assert(stat != LUA_OK);
81  lua_xmove(co, L, 1); /* copy error message */
82  }
83  if (stat != LUA_ERRMEM && /* not a memory error and ... */
84  lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */
85  luaL_where(L, 1); /* add extra info, if available */
86  lua_insert(L, -2);
87  lua_concat(L, 2);
88  }
89  return lua_error(L); /* propagate error */
90  }
91  return r;
92 }
93 
94 
95 static int luaB_cocreate (lua_State *L) {
96  lua_State *NL;
98  NL = lua_newthread(L);
99  lua_pushvalue(L, 1); /* move function to top */
100  lua_xmove(L, NL, 1); /* move function from L to NL */
101  return 1;
102 }
103 
104 
105 static int luaB_cowrap (lua_State *L) {
106  luaB_cocreate(L);
108  return 1;
109 }
110 
111 
112 static int luaB_yield (lua_State *L) {
113  return lua_yield(L, lua_gettop(L));
114 }
115 
116 
117 #define COS_RUN 0
118 #define COS_DEAD 1
119 #define COS_YIELD 2
120 #define COS_NORM 3
121 
122 
123 static const char *const statname[] =
124  {"running", "dead", "suspended", "normal"};
125 
126 
127 static int auxstatus (lua_State *L, lua_State *co) {
128  if (L == co) return COS_RUN;
129  else {
130  switch (lua_status(co)) {
131  case LUA_YIELD:
132  return COS_YIELD;
133  case LUA_OK: {
134  lua_Debug ar;
135  if (lua_getstack(co, 0, &ar)) /* does it have frames? */
136  return COS_NORM; /* it is running */
137  else if (lua_gettop(co) == 0)
138  return COS_DEAD;
139  else
140  return COS_YIELD; /* initial state */
141  }
142  default: /* some error occurred */
143  return COS_DEAD;
144  }
145  }
146 }
147 
148 
149 static int luaB_costatus (lua_State *L) {
150  lua_State *co = getco(L);
151  lua_pushstring(L, statname[auxstatus(L, co)]);
152  return 1;
153 }
154 
155 
156 static int luaB_yieldable (lua_State *L) {
157  lua_State *co = lua_isnone(L, 1) ? L : getco(L);
159  return 1;
160 }
161 
162 
163 static int luaB_corunning (lua_State *L) {
164  int ismain = lua_pushthread(L);
165  lua_pushboolean(L, ismain);
166  return 2;
167 }
168 
169 
170 static int luaB_close (lua_State *L) {
171  lua_State *co = getco(L);
172  int status = auxstatus(L, co);
173  switch (status) {
174  case COS_DEAD: case COS_YIELD: {
175  status = lua_resetthread(co);
176  if (status == LUA_OK) {
177  lua_pushboolean(L, 1);
178  return 1;
179  }
180  else {
181  lua_pushboolean(L, 0);
182  lua_xmove(co, L, 1); /* copy error message */
183  return 2;
184  }
185  }
186  default: /* normal or running coroutine */
187  return luaL_error(L, "cannot close a %s coroutine", statname[status]);
188  }
189 }
190 
191 
192 static const luaL_Reg co_funcs[] = {
193  {"create", luaB_cocreate},
194  {"resume", luaB_coresume},
195  {"running", luaB_corunning},
196  {"status", luaB_costatus},
197  {"wrap", luaB_cowrap},
198  {"yield", luaB_yield},
199  {"isyieldable", luaB_yieldable},
200  {"close", luaB_close},
201  {NULL, NULL}
202 };
203 
204 
205 
207  luaL_newlib(L, co_funcs);
208  return 1;
209 }
210 
LUA_TFUNCTION
#define LUA_TFUNCTION
Definition: lua.h:71
lua_pushliteral
#define lua_pushliteral(L, s)
Definition: lua.h:382
lua_assert
#define lua_assert(c)
Definition: lauxlib.h:170
lua_isyieldable
LUA_API int lua_isyieldable(lua_State *L)
Definition: ldo.c:805
lua_resume
LUA_API int lua_resume(lua_State *L, lua_State *from, int nargs, int *nresults)
Definition: ldo.c:773
luaB_cocreate
static int luaB_cocreate(lua_State *L)
Definition: lcorolib.c:95
luaB_cowrap
static int luaB_cowrap(lua_State *L)
Definition: lcorolib.c:105
luaL_Reg
Definition: lauxlib.h:38
LUA_OK
#define LUA_OK
Definition: lua.h:49
luaB_close
static int luaB_close(lua_State *L)
Definition: lcorolib.c:170
lua_checkstack
LUA_API int lua_checkstack(lua_State *L, int n)
Definition: lapi.c:99
LUA_TSTRING
#define LUA_TSTRING
Definition: lua.h:69
lua_pushthread
LUA_API int lua_pushthread(lua_State *L)
Definition: lapi.c:618
luaB_auxwrap
static int luaB_auxwrap(lua_State *L)
Definition: lcorolib.c:73
luaB_corunning
static int luaB_corunning(lua_State *L)
Definition: lcorolib.c:163
lua_pop
#define lua_pop(L, n)
Definition: lua.h:365
lua_concat
LUA_API void lua_concat(lua_State *L, int n)
Definition: lapi.c:1277
COS_YIELD
#define COS_YIELD
Definition: lcorolib.c:119
lua_type
LUA_API int lua_type(lua_State *L, int idx)
Definition: lapi.c:278
auxstatus
static int auxstatus(lua_State *L, lua_State *co)
Definition: lcorolib.c:127
lua_tothread
LUA_API lua_State * lua_tothread(lua_State *L, int idx)
Definition: lapi.c:456
lua_pushstring
const LUA_API char * lua_pushstring(lua_State *L, const char *s)
Definition: lapi.c:532
luaB_coresume
static int luaB_coresume(lua_State *L)
Definition: lcorolib.c:56
luaL_argexpected
#define luaL_argexpected(L, cond, arg, tname)
Definition: lauxlib.h:136
lua.h
lua_yield
#define lua_yield(L, n)
Definition: lua.h:305
luaB_yield
static int luaB_yield(lua_State *L)
Definition: lcorolib.c:112
lua_insert
#define lua_insert(L, idx)
Definition: lua.h:390
lua_pushcclosure
LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction fn, int n)
Definition: lapi.c:573
COS_RUN
#define COS_RUN
Definition: lcorolib.c:117
lprefix.h
COS_NORM
#define COS_NORM
Definition: lcorolib.c:120
lua_State
Definition: lstate.h:304
statname
static const char *const statname[]
Definition: lcorolib.c:123
lua_getstack
LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
Definition: ldebug.c:160
getco
static lua_State * getco(lua_State *L)
Definition: lcorolib.c:21
lua_gettop
LUA_API int lua_gettop(lua_State *L)
Definition: lapi.c:169
lauxlib.h
lualib.h
lua_pushboolean
LUA_API void lua_pushboolean(lua_State *L, int b)
Definition: lapi.c:599
lua_pushvalue
LUA_API void lua_pushvalue(lua_State *L, int idx)
Definition: lapi.c:264
luaB_costatus
static int luaB_costatus(lua_State *L)
Definition: lcorolib.c:149
luaL_checktype
LUALIB_API void luaL_checktype(lua_State *L, int arg, int t)
Definition: lauxlib.c:390
COS_DEAD
#define COS_DEAD
Definition: lcorolib.c:118
lua_status
LUA_API int lua_status(lua_State *L)
Definition: lapi.c:1118
LUA_YIELD
#define LUA_YIELD
Definition: lua.h:50
luaopen_coroutine
LUAMOD_API int luaopen_coroutine(lua_State *L)
Definition: lcorolib.c:206
auxresume
static int auxresume(lua_State *L, lua_State *co, int narg)
Definition: lcorolib.c:32
LUAMOD_API
#define LUAMOD_API
Definition: luaconf.h:291
lua_xmove
LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
Definition: lapi.c:121
lua_resetthread
LUA_API int lua_resetthread(lua_State *L)
Definition: lstate.c:345
luaL_newlib
#define luaL_newlib(L, l)
Definition: lauxlib.h:130
luaL_error
LUALIB_API int luaL_error(lua_State *L, const char *fmt,...)
Definition: lauxlib.c:234
luaL_where
LUALIB_API void luaL_where(lua_State *L, int level)
Definition: lauxlib.c:216
lua_isnone
#define lua_isnone(L, n)
Definition: lua.h:379
luaB_yieldable
static int luaB_yieldable(lua_State *L)
Definition: lcorolib.c:156
lua_Debug
Definition: lua.h:470
co_funcs
static const luaL_Reg co_funcs[]
Definition: lcorolib.c:192
lua_upvalueindex
#define lua_upvalueindex(i)
Definition: lua.h:45
LUA_ERRMEM
#define LUA_ERRMEM
Definition: lua.h:53
lua_newthread
LUA_API lua_State * lua_newthread(lua_State *L)
Definition: lstate.c:285
lua_error
LUA_API int lua_error(lua_State *L)
Definition: lapi.c:1230


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:44