mirror of https://github.com/rusefi/lua.git
cleaner API for coroutines
This commit is contained in:
parent
0e54d2be36
commit
2419f2bf02
19
lapi.c
19
lapi.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lapi.c,v 2.17 2004/08/17 17:45:45 roberto Exp roberto $
|
||||
** $Id: lapi.c,v 2.18 2004/08/30 13:44:44 roberto Exp roberto $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -97,6 +97,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
|
|||
if (from == to) return;
|
||||
lua_lock(to);
|
||||
api_checknelems(from, n);
|
||||
api_check(L, G(from) == G(to));
|
||||
from->top -= n;
|
||||
for (i = 0; i < n; i++) {
|
||||
setobj2s(to, to->top, from->top + i);
|
||||
|
@ -479,6 +480,15 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
|
|||
}
|
||||
|
||||
|
||||
LUA_API int lua_pushthread (lua_State *L) {
|
||||
lua_lock(L);
|
||||
setthvalue(L, L->top, L);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return (G(L)->mainthread == L);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
|
@ -650,7 +660,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
|||
case LUA_TTABLE: {
|
||||
hvalue(obj)->metatable = mt;
|
||||
if (mt)
|
||||
luaC_objbarrier(L, hvalue(obj), mt);
|
||||
luaC_objbarriert(L, hvalue(obj), mt);
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
|
@ -816,6 +826,11 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
|
|||
}
|
||||
|
||||
|
||||
LUA_API int lua_threadstatus (lua_State *L) {
|
||||
return L->status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Garbage-collection function
|
||||
*/
|
||||
|
|
40
lbaselib.c
40
lbaselib.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lbaselib.c,v 1.156 2004/08/30 18:35:14 roberto Exp roberto $
|
||||
** $Id: lbaselib.c,v 1.157 2004/09/03 13:16:48 roberto Exp roberto $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -523,9 +523,13 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
|
|||
int status;
|
||||
if (!lua_checkstack(co, narg))
|
||||
luaL_error(L, "too many arguments to resume");
|
||||
if (lua_threadstatus(co) == 0 && lua_gettop(co) == 0) {
|
||||
lua_pushliteral(L, "cannot resume dead coroutine");
|
||||
return -1; /* error flag */
|
||||
}
|
||||
lua_xmove(L, co, narg);
|
||||
status = lua_resume(co, narg);
|
||||
if (status == 0) {
|
||||
if (status == 0 || status == LUA_YIELD) {
|
||||
int nres = lua_gettop(co);
|
||||
if (!lua_checkstack(L, nres))
|
||||
luaL_error(L, "too many results to resume");
|
||||
|
@ -599,22 +603,44 @@ static int luaB_costatus (lua_State *L) {
|
|||
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||
if (L == co) lua_pushliteral(L, "running");
|
||||
else {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) == 0 && lua_gettop(co) == 0)
|
||||
lua_pushliteral(L, "dead");
|
||||
else
|
||||
lua_pushliteral(L, "suspended");
|
||||
switch (lua_threadstatus(co)) {
|
||||
case LUA_YIELD:
|
||||
lua_pushliteral(L, "suspended");
|
||||
break;
|
||||
case 0: {
|
||||
lua_Debug ar;
|
||||
if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */
|
||||
lua_pushliteral(L, "normal"); /* it is running */
|
||||
else if (lua_gettop(co) == 0)
|
||||
lua_pushliteral(L, "dead");
|
||||
else
|
||||
lua_pushliteral(L, "suspended"); /* initial state */
|
||||
break;
|
||||
}
|
||||
default: /* some error occured */
|
||||
lua_pushliteral(L, "dead");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_cocurrent (lua_State *L) {
|
||||
if (lua_pushthread(L))
|
||||
return 0; /* main thread is not a coroutine */
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_reg co_funcs[] = {
|
||||
{"create", luaB_cocreate},
|
||||
{"wrap", luaB_cowrap},
|
||||
{"resume", luaB_coresume},
|
||||
{"yield", luaB_yield},
|
||||
{"status", luaB_costatus},
|
||||
{"current", luaB_cocurrent},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
32
ldo.c
32
ldo.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ldo.c,v 2.8 2004/09/03 15:48:56 roberto Exp roberto $
|
||||
** $Id: ldo.c,v 2.9 2004/09/08 14:23:09 roberto Exp roberto $
|
||||
** Stack and Call structure of Lua
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -358,7 +358,7 @@ static void resume (lua_State *L, void *ud) {
|
|||
StkId firstResult;
|
||||
int nargs = *cast(int *, ud);
|
||||
CallInfo *ci = L->ci;
|
||||
if (!L->isSuspended) {
|
||||
if (L->status != LUA_YIELD) {
|
||||
lua_assert(ci == L->base_ci && nargs < L->top - L->base);
|
||||
luaD_precall(L, L->top - (nargs + 1), LUA_MULTRET); /* start coroutine */
|
||||
}
|
||||
|
@ -372,10 +372,11 @@ static void resume (lua_State *L, void *ud) {
|
|||
if (nresults >= 0) L->top = L->ci->top;
|
||||
} /* else yielded inside a hook: just continue its execution */
|
||||
}
|
||||
L->isSuspended = 0;
|
||||
L->status = 0;
|
||||
firstResult = luaV_execute(L, L->ci - L->base_ci);
|
||||
if (firstResult != NULL) /* return? */
|
||||
if (firstResult != NULL) { /* return? */
|
||||
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -393,25 +394,20 @@ LUA_API int lua_resume (lua_State *L, int nargs) {
|
|||
lu_byte old_allowhooks;
|
||||
lua_lock(L);
|
||||
lua_assert(L->errfunc == 0 && L->nCcalls == 0);
|
||||
if (!L->isSuspended) {
|
||||
if (L->ci == L->base_ci) { /* no activation record? */
|
||||
if (nargs >= L->top - L->base)
|
||||
return resume_error(L, "cannot resume dead coroutine");
|
||||
}
|
||||
else
|
||||
if (L->status != LUA_YIELD) {
|
||||
if (L->status != 0)
|
||||
return resume_error(L, "cannot resume dead coroutine");
|
||||
else if (L->ci != L->base_ci)
|
||||
return resume_error(L, "cannot resume non-suspended coroutine");
|
||||
}
|
||||
old_allowhooks = L->allowhook;
|
||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||
if (status != 0) { /* error? */
|
||||
L->ci = L->base_ci; /* go back to initial level */
|
||||
L->base = L->ci->base;
|
||||
L->nCcalls = 0;
|
||||
luaF_close(L, L->base); /* close eventual pending closures */
|
||||
seterrorobj(L, status, L->base);
|
||||
L->allowhook = old_allowhooks;
|
||||
restore_stack_limit(L);
|
||||
L->status = status; /* mark thread as `dead' */
|
||||
seterrorobj(L, status, L->top);
|
||||
}
|
||||
else
|
||||
status = L->status;
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
@ -431,7 +427,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
|
|||
L->top = L->base + nresults;
|
||||
}
|
||||
} /* else it's an yield inside a hook: nothing to do */
|
||||
L->isSuspended = 1;
|
||||
L->status = LUA_YIELD;
|
||||
lua_unlock(L);
|
||||
return -1;
|
||||
}
|
||||
|
|
4
lstate.c
4
lstate.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.c,v 2.12 2004/08/30 13:44:44 roberto Exp $
|
||||
** $Id: lstate.c,v 2.13 2004/09/08 14:23:09 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -114,7 +114,7 @@ static void preinit_state (lua_State *L, global_State *g) {
|
|||
L->openupval = NULL;
|
||||
L->size_ci = 0;
|
||||
L->nCcalls = 0;
|
||||
L->isSuspended = 0;
|
||||
L->status = 0;
|
||||
L->base_ci = L->ci = NULL;
|
||||
L->errfunc = 0;
|
||||
setnilvalue(gt(L));
|
||||
|
|
4
lstate.h
4
lstate.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.h,v 2.6 2004/08/24 20:12:06 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 2.7 2004/08/30 13:44:44 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -111,7 +111,7 @@ struct lua_State {
|
|||
unsigned short nCcalls; /* number of nested C calls */
|
||||
lu_byte hookmask;
|
||||
lu_byte allowhook;
|
||||
lu_byte isSuspended;
|
||||
lu_byte status;
|
||||
int basehookcount;
|
||||
int hookcount;
|
||||
lua_Hook hook;
|
||||
|
|
15
lua.h
15
lua.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lua.h,v 1.191 2004/06/02 17:37:03 roberto Exp roberto $
|
||||
** $Id: lua.h,v 1.192 2004/06/04 15:30:53 roberto Exp roberto $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
||||
** http://www.lua.org mailto:info@lua.org
|
||||
|
@ -37,11 +37,12 @@
|
|||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
|
||||
|
||||
|
||||
/* error codes for `lua_pcall' */
|
||||
#define LUA_ERRRUN 1
|
||||
#define LUA_ERRSYNTAX 2
|
||||
#define LUA_ERRMEM 3
|
||||
#define LUA_ERRERR 4
|
||||
/* return codes for `lua_pcall', `lua_resume', and `lua_threadstatus' */
|
||||
#define LUA_YIELD 1
|
||||
#define LUA_ERRRUN 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
|
@ -165,6 +166,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
|
|||
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
|
||||
LUA_API void lua_pushboolean (lua_State *L, int b);
|
||||
LUA_API void lua_pushlightuserdata (lua_State *L, void *p);
|
||||
LUA_API int lua_pushthread (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -208,6 +210,7 @@ LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data);
|
|||
*/
|
||||
LUA_API int lua_yield (lua_State *L, int nresults);
|
||||
LUA_API int lua_resume (lua_State *L, int narg);
|
||||
LUA_API int lua_threadstatus (lua_State *L);
|
||||
|
||||
/*
|
||||
** garbage-collection function and options
|
||||
|
|
4
lvm.c
4
lvm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.c,v 2.12 2004/08/10 19:17:23 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.13 2004/08/12 14:19:51 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -398,7 +398,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
|
|||
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
|
||||
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
|
||||
traceexec(L, pc); /***/
|
||||
if (L->isSuspended) { /* did hook yield? */
|
||||
if (L->status == LUA_YIELD) { /* did hook yield? */
|
||||
L->ci->savedpc = pc - 1;
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue