mirror of
https://github.com/lua/lua.git
synced 2025-02-04 06:13:04 +08:00
threads now are real Lua objects, subject to garbage collection
This commit is contained in:
parent
0fd91b1b08
commit
96e15b8501
20
lapi.c
20
lapi.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 1.212 2002/08/30 19:09:21 roberto Exp roberto $
|
** $Id: lapi.c,v 1.213 2002/09/20 17:01:24 roberto Exp roberto $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -115,6 +115,18 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LUA_API lua_State *lua_newthread (lua_State *L) {
|
||||||
|
lua_State *L1;
|
||||||
|
lua_lock(L);
|
||||||
|
L1 = luaE_newthread(L);
|
||||||
|
setthvalue(L->top, L1);
|
||||||
|
api_incr_top(L);
|
||||||
|
lua_unlock(L);
|
||||||
|
lua_userstateopen(L1);
|
||||||
|
return L1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** basic stack manipulation
|
** basic stack manipulation
|
||||||
*/
|
*/
|
||||||
@ -322,6 +334,12 @@ LUA_API void *lua_touserdata (lua_State *L, int index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LUA_API lua_State *lua_tothread (lua_State *L, int index) {
|
||||||
|
StkId o = luaA_indexAcceptable(L, index);
|
||||||
|
return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API const void *lua_topointer (lua_State *L, int index) {
|
LUA_API const void *lua_topointer (lua_State *L, int index) {
|
||||||
StkId o = luaA_indexAcceptable(L, index);
|
StkId o = luaA_indexAcceptable(L, index);
|
||||||
if (o == NULL) return NULL;
|
if (o == NULL) return NULL;
|
||||||
|
78
lbaselib.c
78
lbaselib.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lbaselib.c,v 1.99 2002/09/16 19:49:45 roberto Exp roberto $
|
** $Id: lbaselib.c,v 1.100 2002/10/22 19:41:08 roberto Exp roberto $
|
||||||
** Basic library
|
** Basic library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -362,6 +362,9 @@ static int luaB_tostring (lua_State *L) {
|
|||||||
case LUA_TLIGHTUSERDATA:
|
case LUA_TLIGHTUSERDATA:
|
||||||
sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
|
sprintf(buff, "userdata: %p", lua_touserdata(L, 1));
|
||||||
break;
|
break;
|
||||||
|
case LUA_TTHREAD:
|
||||||
|
sprintf(buff, "thread: %p", (void *)lua_tothread(L, 1));
|
||||||
|
break;
|
||||||
case LUA_TNIL:
|
case LUA_TNIL:
|
||||||
lua_pushliteral(L, "nil");
|
lua_pushliteral(L, "nil");
|
||||||
return 1;
|
return 1;
|
||||||
@ -535,26 +538,40 @@ static const luaL_reg base_funcs[] = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static int luaB_resume (lua_State *L) {
|
static int luaB_auxresume (lua_State *L, lua_State *co) {
|
||||||
lua_State *co = (lua_State *)lua_unboxpointer(L, lua_upvalueindex(1));
|
|
||||||
int status;
|
int status;
|
||||||
lua_settop(L, 0);
|
int oldtop = lua_gettop(L);
|
||||||
status = lua_resume(L, co);
|
status = lua_resume(L, co);
|
||||||
if (status != 0)
|
return (status != 0) ? -1 : lua_gettop(L) - oldtop;
|
||||||
return lua_error(L);
|
|
||||||
return lua_gettop(L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int luaB_coresume (lua_State *L) {
|
||||||
static int gc_coroutine (lua_State *L) {
|
lua_State *co = lua_tothread(L, 1);
|
||||||
lua_State *co = (lua_State *)lua_unboxpointer(L, 1);
|
int r;
|
||||||
lua_closethread(L, co);
|
luaL_arg_check(L, co, 1, "coroutine/thread expected");
|
||||||
return 0;
|
r = luaB_auxresume(L, co);
|
||||||
|
if (r < 0) {
|
||||||
|
lua_pushboolean(L, 0);
|
||||||
|
lua_insert(L, -2);
|
||||||
|
return 2; /* return false + error message */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lua_pushboolean(L, 1);
|
||||||
|
lua_insert(L, -(r + 1));
|
||||||
|
return r + 1; /* return true + `resume' returns */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int luaB_coroutine (lua_State *L) {
|
static int luaB_auxwrap (lua_State *L) {
|
||||||
|
int r = luaB_auxresume(L, lua_tothread(L, lua_upvalueindex(1)));
|
||||||
|
if (r < 0) lua_error(L);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int luaB_cocreate (lua_State *L) {
|
||||||
lua_State *NL;
|
lua_State *NL;
|
||||||
int ref;
|
int ref;
|
||||||
int i;
|
int i;
|
||||||
@ -562,20 +579,21 @@ static int luaB_coroutine (lua_State *L) {
|
|||||||
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
|
luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
|
||||||
"Lua function expected");
|
"Lua function expected");
|
||||||
NL = lua_newthread(L);
|
NL = lua_newthread(L);
|
||||||
if (NL == NULL) return luaL_error(L, "unable to create new thread");
|
|
||||||
/* move function and arguments from L to NL */
|
/* move function and arguments from L to NL */
|
||||||
for (i=0; i<n; i++) {
|
for (i = 1; i <= n; i++) {
|
||||||
|
lua_pushvalue(L, i);
|
||||||
ref = lua_ref(L, 1);
|
ref = lua_ref(L, 1);
|
||||||
lua_getref(NL, ref);
|
lua_getref(NL, ref);
|
||||||
lua_insert(NL, 1);
|
|
||||||
lua_unref(L, ref);
|
lua_unref(L, ref);
|
||||||
}
|
}
|
||||||
lua_cobegin(NL, n-1);
|
lua_cobegin(NL, n-1);
|
||||||
lua_boxpointer(L, NL);
|
return 1;
|
||||||
lua_pushliteral(L, "Coroutine");
|
}
|
||||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
||||||
lua_setmetatable(L, -2);
|
|
||||||
lua_pushcclosure(L, luaB_resume, 1);
|
static int luaB_cowrap (lua_State *L) {
|
||||||
|
luaB_cocreate(L);
|
||||||
|
lua_pushcclosure(L, luaB_auxwrap, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,23 +603,13 @@ static int luaB_yield (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const luaL_reg co_funcs[] = {
|
static const luaL_reg co_funcs[] = {
|
||||||
{"create", luaB_coroutine},
|
{"create", luaB_cocreate},
|
||||||
|
{"wrap", luaB_cowrap},
|
||||||
|
{"resume", luaB_coresume},
|
||||||
{"yield", luaB_yield},
|
{"yield", luaB_yield},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void co_open (lua_State *L) {
|
|
||||||
luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0);
|
|
||||||
/* create metatable for coroutines */
|
|
||||||
lua_pushliteral(L, "Coroutine");
|
|
||||||
lua_newtable(L);
|
|
||||||
lua_pushliteral(L, "__gc");
|
|
||||||
lua_pushcfunction(L, gc_coroutine);
|
|
||||||
lua_rawset(L, -3);
|
|
||||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
@ -625,7 +633,7 @@ static void base_open (lua_State *L) {
|
|||||||
|
|
||||||
LUALIB_API int lua_baselibopen (lua_State *L) {
|
LUALIB_API int lua_baselibopen (lua_State *L) {
|
||||||
base_open(L);
|
base_open(L);
|
||||||
co_open(L);
|
luaL_opennamedlib(L, LUA_COLIBNAME, co_funcs, 0);
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_setglobal(L, REQTAB);
|
lua_setglobal(L, REQTAB);
|
||||||
return 0;
|
return 0;
|
||||||
|
16
ldo.c
16
ldo.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 1.195 2002/10/08 18:46:08 roberto Exp roberto $
|
** $Id: ldo.c,v 1.196 2002/10/09 13:42:01 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -343,10 +343,15 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
|
|||||||
int status;
|
int status;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
ci = co->ci;
|
ci = co->ci;
|
||||||
if (ci == co->base_ci) /* no activation record? ?? */
|
if (ci == co->base_ci) { /* no activation record? ?? */
|
||||||
luaG_runerror(L, "cannot resume dead thread");
|
luaO_pushfstring(L, "cannot resume dead thread");
|
||||||
if (co->errorJmp != NULL) /* ?? */
|
status = LUA_ERRRUN;
|
||||||
luaG_runerror(L, "cannot resume active thread");
|
}
|
||||||
|
else if (co->errorJmp != NULL) { /* ?? */
|
||||||
|
luaO_pushfstring(L, "cannot resume active thread");
|
||||||
|
status = LUA_ERRRUN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
status = luaD_rawrunprotected(co, resume, &numres);
|
status = luaD_rawrunprotected(co, resume, &numres);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
move_results(L, co->top - numres, co->top);
|
move_results(L, co->top - numres, co->top);
|
||||||
@ -354,6 +359,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *co) {
|
|||||||
setobj(L->top++, co->top - 1); /* move error message to other stack */
|
setobj(L->top++, co->top - 1); /* move error message to other stack */
|
||||||
co->ci = co->base_ci; /* `kill' thread */
|
co->ci = co->base_ci; /* `kill' thread */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
87
lgc.c
87
lgc.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 1.152 2002/10/08 18:46:08 roberto Exp roberto $
|
** $Id: lgc.c,v 1.153 2002/10/22 17:58:14 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -99,6 +99,32 @@ static void markclosure (GCState *st, Closure *cl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void checkstacksizes (lua_State *L, StkId max) {
|
||||||
|
int used = L->ci - L->base_ci; /* number of `ci' in use */
|
||||||
|
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
|
||||||
|
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
|
||||||
|
used = max - L->stack; /* part of stack in use */
|
||||||
|
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
|
||||||
|
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void markstack (GCState *st, lua_State *L1) {
|
||||||
|
StkId o, lim;
|
||||||
|
CallInfo *ci;
|
||||||
|
markobject(st, gt(L1));
|
||||||
|
for (o=L1->stack; o<L1->top; o++)
|
||||||
|
markobject(st, o);
|
||||||
|
lim = o;
|
||||||
|
for (ci = L1->base_ci; ci <= L1->ci; ci++) {
|
||||||
|
lua_assert(ci->top <= L1->stack_last);
|
||||||
|
if (lim < ci->top) lim = ci->top;
|
||||||
|
}
|
||||||
|
for (; o<=lim; o++) setnilvalue(o);
|
||||||
|
checkstacksizes(L1, lim);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void reallymarkobject (GCState *st, GCObject *o) {
|
static void reallymarkobject (GCState *st, GCObject *o) {
|
||||||
setbit(o->gch.marked, 0); /* mark object */
|
setbit(o->gch.marked, 0); /* mark object */
|
||||||
switch (o->gch.tt) {
|
switch (o->gch.tt) {
|
||||||
@ -115,46 +141,11 @@ static void reallymarkobject (GCState *st, GCObject *o) {
|
|||||||
st->tmark = &o->h;
|
st->tmark = &o->h;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case LUA_TTHREAD: {
|
||||||
|
markstack(st, &o->th);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void checkstacksizes (lua_State *L, StkId max) {
|
|
||||||
int used = L->ci - L->base_ci; /* number of `ci' in use */
|
|
||||||
if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)
|
|
||||||
luaD_reallocCI(L, L->size_ci/2); /* still big enough... */
|
|
||||||
used = max - L->stack; /* part of stack in use */
|
|
||||||
if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)
|
|
||||||
luaD_reallocstack(L, L->stacksize/2); /* still big enough... */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void traversestacks (GCState *st) {
|
|
||||||
lua_State *L1 = st->L;
|
|
||||||
do { /* for each thread */
|
|
||||||
StkId o, lim;
|
|
||||||
CallInfo *ci;
|
|
||||||
if (ttisnil(gt(L1))) { /* incomplete state? */
|
|
||||||
lua_assert(L1 != st->L);
|
|
||||||
L1 = L1->next;
|
|
||||||
luaE_closethread(st->L, L1->previous); /* collect it */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
markobject(st, gt(L1));
|
|
||||||
for (o=L1->stack; o<L1->top; o++)
|
|
||||||
markobject(st, o);
|
|
||||||
lim = o;
|
|
||||||
for (ci = L1->base_ci; ci <= L1->ci; ci++) {
|
|
||||||
lua_assert(ci->top <= L1->stack_last);
|
|
||||||
if (lim < ci->top) lim = ci->top;
|
|
||||||
}
|
|
||||||
for (; o<=lim; o++) setnilvalue(o);
|
|
||||||
checkstacksizes(L1, lim);
|
|
||||||
lua_assert(L1->previous->next == L1 && L1->next->previous == L1);
|
|
||||||
L1 = L1->next;
|
|
||||||
} while (L1 != st->L);
|
|
||||||
markobject(st, defaultmeta(L1));
|
|
||||||
markobject(st, registry(L1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -292,6 +283,11 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break;
|
case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break;
|
||||||
case LUA_TUPVAL: luaM_freelem(L, &o->uv); break;
|
case LUA_TUPVAL: luaM_freelem(L, &o->uv); break;
|
||||||
case LUA_TTABLE: luaH_free(L, &o->h); break;
|
case LUA_TTABLE: luaH_free(L, &o->h); break;
|
||||||
|
case LUA_TTHREAD: {
|
||||||
|
lua_assert(&o->th != L && &o->th != G(L)->mainthread);
|
||||||
|
luaE_freethread(L, &o->th);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case LUA_TSTRING: {
|
case LUA_TSTRING: {
|
||||||
luaM_free(L, o, sizestring((&o->ts)->tsv.len));
|
luaM_free(L, o, sizestring((&o->ts)->tsv.len));
|
||||||
break;
|
break;
|
||||||
@ -389,13 +385,24 @@ void luaC_sweep (lua_State *L, int all) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* mark root set */
|
||||||
|
static void markroot (GCState *st) {
|
||||||
|
lua_State *L = st->L;
|
||||||
|
markobject(st, defaultmeta(L));
|
||||||
|
markobject(st, registry(L));
|
||||||
|
markstack(st, G(L)->mainthread);
|
||||||
|
if (L != G(L)->mainthread) /* another thread is running? */
|
||||||
|
reallymarkobject(st, cast(GCObject *, L)); /* cannot collect it */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mark (lua_State *L) {
|
static void mark (lua_State *L) {
|
||||||
GCState st;
|
GCState st;
|
||||||
Table *toclear;
|
Table *toclear;
|
||||||
st.L = L;
|
st.L = L;
|
||||||
st.tmark = NULL;
|
st.tmark = NULL;
|
||||||
st.toclear = NULL;
|
st.toclear = NULL;
|
||||||
traversestacks(&st); /* mark all stacks */
|
markroot(&st);
|
||||||
propagatemarks(&st); /* mark all reachable objects */
|
propagatemarks(&st); /* mark all reachable objects */
|
||||||
toclear = st.toclear; /* weak tables; to be cleared */
|
toclear = st.toclear; /* weak tables; to be cleared */
|
||||||
st.toclear = NULL;
|
st.toclear = NULL;
|
||||||
|
67
lobject.h
67
lobject.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lobject.h,v 1.148 2002/10/16 20:40:58 roberto Exp roberto $
|
** $Id: lobject.h,v 1.149 2002/10/22 17:18:28 roberto Exp roberto $
|
||||||
** Type definitions for Lua objects
|
** Type definitions for Lua objects
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* tags for values visible from Lua */
|
/* tags for values visible from Lua */
|
||||||
#define NUM_TAGS LUA_TUSERDATA
|
#define NUM_TAGS LUA_TTHREAD
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -23,23 +23,34 @@
|
|||||||
#define LUA_TUPVAL (NUM_TAGS+2)
|
#define LUA_TUPVAL (NUM_TAGS+2)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Union of all collectable objects
|
||||||
|
*/
|
||||||
|
typedef union GCObject GCObject;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Common header for all collectable objects
|
** Common header for all collectable objects
|
||||||
*/
|
*/
|
||||||
typedef struct GCheader {
|
typedef struct GCheader {
|
||||||
union GCObject *next; /* pointer to next object */
|
GCObject *next; /* pointer to next object */
|
||||||
lu_byte tt; /* object type */
|
lu_byte tt; /* object type */
|
||||||
lu_byte marked; /* GC informations */
|
lu_byte marked; /* GC informations */
|
||||||
} GCheader;
|
} GCheader;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** common header in macro form, to be included in other objects
|
||||||
|
*/
|
||||||
|
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Union of all Lua values
|
** Union of all Lua values
|
||||||
*/
|
*/
|
||||||
typedef union {
|
typedef union {
|
||||||
union GCObject *gc;
|
GCObject *gc;
|
||||||
void *p;
|
void *p;
|
||||||
lua_Number n;
|
lua_Number n;
|
||||||
int b;
|
int b;
|
||||||
@ -63,6 +74,7 @@ typedef struct lua_TObject {
|
|||||||
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
|
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
|
||||||
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
|
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
|
||||||
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
|
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
|
||||||
|
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
|
||||||
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
||||||
|
|
||||||
/* Macros to access values */
|
/* Macros to access values */
|
||||||
@ -75,6 +87,7 @@ typedef struct lua_TObject {
|
|||||||
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
|
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
|
||||||
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
|
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
|
||||||
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
|
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
|
||||||
|
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
|
||||||
|
|
||||||
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
|
#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))
|
||||||
|
|
||||||
@ -101,6 +114,11 @@ typedef struct lua_TObject {
|
|||||||
i_o->value.gc=cast(GCObject *, (x)); \
|
i_o->value.gc=cast(GCObject *, (x)); \
|
||||||
lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); }
|
lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); }
|
||||||
|
|
||||||
|
#define setthvalue(obj,x) \
|
||||||
|
{ TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \
|
||||||
|
i_o->value.gc=cast(GCObject *, (x)); \
|
||||||
|
lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); }
|
||||||
|
|
||||||
#define setclvalue(obj,x) \
|
#define setclvalue(obj,x) \
|
||||||
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \
|
{ TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \
|
||||||
i_o->value.gc=cast(GCObject *, (x)); \
|
i_o->value.gc=cast(GCObject *, (x)); \
|
||||||
@ -142,9 +160,7 @@ typedef TObject *StkId; /* index to stack elements */
|
|||||||
typedef union TString {
|
typedef union TString {
|
||||||
L_Umaxalign dummy; /* ensures maximum alignment for strings */
|
L_Umaxalign dummy; /* ensures maximum alignment for strings */
|
||||||
struct {
|
struct {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
lu_byte reserved;
|
lu_byte reserved;
|
||||||
lu_hash hash;
|
lu_hash hash;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -160,9 +176,7 @@ typedef union TString {
|
|||||||
typedef union Udata {
|
typedef union Udata {
|
||||||
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
|
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
|
||||||
struct {
|
struct {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
struct Table *metatable;
|
struct Table *metatable;
|
||||||
size_t len;
|
size_t len;
|
||||||
} uv;
|
} uv;
|
||||||
@ -175,9 +189,7 @@ typedef union Udata {
|
|||||||
** Function Prototypes
|
** Function Prototypes
|
||||||
*/
|
*/
|
||||||
typedef struct Proto {
|
typedef struct Proto {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
TObject *k; /* constants used by the function */
|
TObject *k; /* constants used by the function */
|
||||||
Instruction *code;
|
Instruction *code;
|
||||||
struct Proto **p; /* functions defined inside the function */
|
struct Proto **p; /* functions defined inside the function */
|
||||||
@ -210,9 +222,7 @@ typedef struct LocVar {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct UpVal {
|
typedef struct UpVal {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
TObject *v; /* points to stack or to its own value */
|
TObject *v; /* points to stack or to its own value */
|
||||||
TObject value; /* the value (when closed) */
|
TObject value; /* the value (when closed) */
|
||||||
} UpVal;
|
} UpVal;
|
||||||
@ -223,9 +233,7 @@ typedef struct UpVal {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct CClosure {
|
typedef struct CClosure {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
lu_byte isC; /* 0 for Lua functions, 1 for C functions */
|
lu_byte isC; /* 0 for Lua functions, 1 for C functions */
|
||||||
lu_byte nupvalues;
|
lu_byte nupvalues;
|
||||||
lua_CFunction f;
|
lua_CFunction f;
|
||||||
@ -234,9 +242,7 @@ typedef struct CClosure {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct LClosure {
|
typedef struct LClosure {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
lu_byte isC;
|
lu_byte isC;
|
||||||
lu_byte nupvalues; /* first five fields must be equal to CClosure!! */
|
lu_byte nupvalues; /* first five fields must be equal to CClosure!! */
|
||||||
struct Proto *p;
|
struct Proto *p;
|
||||||
@ -267,9 +273,7 @@ typedef struct Node {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct Table {
|
typedef struct Table {
|
||||||
union GCObject *next; /* pointer to next object */
|
CommonHeader;
|
||||||
lu_byte tt; /* object type */
|
|
||||||
lu_byte marked; /* GC informations */
|
|
||||||
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||||
lu_byte mode;
|
lu_byte mode;
|
||||||
lu_byte lsizenode; /* log2 of size of `node' array */
|
lu_byte lsizenode; /* log2 of size of `node' array */
|
||||||
@ -298,19 +302,6 @@ typedef struct Table {
|
|||||||
#define sizearray(t) ((t)->sizearray)
|
#define sizearray(t) ((t)->sizearray)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Union of all collectable objects
|
|
||||||
*/
|
|
||||||
typedef union GCObject {
|
|
||||||
GCheader gch;
|
|
||||||
union TString ts;
|
|
||||||
union Udata u;
|
|
||||||
union Closure cl;
|
|
||||||
struct Table h;
|
|
||||||
struct Proto p;
|
|
||||||
struct UpVal uv;
|
|
||||||
} GCObject;
|
|
||||||
|
|
||||||
|
|
||||||
extern const TObject luaO_nilobject;
|
extern const TObject luaO_nilobject;
|
||||||
|
|
||||||
|
103
lstate.c
103
lstate.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 1.106 2002/10/08 18:46:08 roberto Exp roberto $
|
** $Id: lstate.c,v 1.107 2002/10/22 17:58:14 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -19,11 +19,30 @@
|
|||||||
#include "ltm.h"
|
#include "ltm.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** macro to allow the inclusion of user information in Lua state
|
||||||
|
*/
|
||||||
|
#ifndef LUA_USERSTATE
|
||||||
|
#define EXTRASPACE 0
|
||||||
|
#else
|
||||||
|
union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;};
|
||||||
|
#define EXTRASPACE (sizeof(UEXTRASPACE))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void close_state (lua_State *L);
|
static void close_state (lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
|
static lua_State *newthread (lua_State *L) {
|
||||||
|
lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE);
|
||||||
|
if (block == NULL) return NULL;
|
||||||
|
else {
|
||||||
|
block += EXTRASPACE;
|
||||||
|
return cast(lua_State *, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** you can change this function through the official API:
|
** you can change this function through the official API:
|
||||||
** call `lua_setpanicf'
|
** call `lua_setpanicf'
|
||||||
@ -34,19 +53,19 @@ static int default_panic (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void stack_init (lua_State *L, lua_State *OL) {
|
static void stack_init (lua_State *L1, lua_State *L) {
|
||||||
L->stack = luaM_newvector(OL, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TObject);
|
||||||
L->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
|
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
|
||||||
L->top = L->stack;
|
L1->top = L1->stack;
|
||||||
L->stack_last = L->stack+(L->stacksize - EXTRA_STACK)-1;
|
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
|
||||||
L->base_ci = luaM_newvector(OL, BASIC_CI_SIZE, CallInfo);
|
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
|
||||||
L->ci = L->base_ci;
|
L1->ci = L1->base_ci;
|
||||||
L->ci->state = CI_C; /* not a Lua function */
|
L1->ci->state = CI_C; /* not a Lua function */
|
||||||
setnilvalue(L->top++); /* `function' entry for this `ci' */
|
setnilvalue(L1->top++); /* `function' entry for this `ci' */
|
||||||
L->ci->base = L->top;
|
L1->ci->base = L1->top;
|
||||||
L->ci->top = L->top + LUA_MINSTACK;
|
L1->ci->top = L1->top + LUA_MINSTACK;
|
||||||
L->size_ci = BASIC_CI_SIZE;
|
L1->size_ci = BASIC_CI_SIZE;
|
||||||
L->end_ci = L->base_ci + L->size_ci;
|
L1->end_ci = L1->base_ci + L1->size_ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -57,6 +76,7 @@ static void f_luaopen (lua_State *L, void *ud) {
|
|||||||
UNUSED(ud);
|
UNUSED(ud);
|
||||||
/* create a new global state */
|
/* create a new global state */
|
||||||
L->l_G = luaM_new(L, global_State);
|
L->l_G = luaM_new(L, global_State);
|
||||||
|
G(L)->mainthread = L;
|
||||||
G(L)->GCthreshold = 0; /* mark it as unfinished state */
|
G(L)->GCthreshold = 0; /* mark it as unfinished state */
|
||||||
G(L)->strt.size = 0;
|
G(L)->strt.size = 0;
|
||||||
G(L)->strt.nuse = 0;
|
G(L)->strt.nuse = 0;
|
||||||
@ -103,31 +123,22 @@ static void preinit_state (lua_State *L) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API lua_State *lua_newthread (lua_State *OL) {
|
lua_State *luaE_newthread (lua_State *L) {
|
||||||
lua_State *L;
|
lua_State *L1 = newthread(L);
|
||||||
lua_lock(OL);
|
luaC_link(L, cast(GCObject *, L1), LUA_TTHREAD);
|
||||||
L = luaM_new(OL, lua_State);
|
preinit_state(L1);
|
||||||
preinit_state(L);
|
L1->l_G = L->l_G;
|
||||||
L->l_G = OL->l_G;
|
stack_init(L1, L); /* init stack */
|
||||||
OL->next->previous = L; /* insert L into linked list */
|
setobj(gt(L1), gt(L)); /* share table of globals */
|
||||||
L->next = OL->next;
|
return L1;
|
||||||
OL->next = L;
|
|
||||||
L->previous = OL;
|
|
||||||
stack_init(L, OL); /* init stack */
|
|
||||||
setobj(gt(L), gt(OL)); /* share table of globals */
|
|
||||||
lua_unlock(OL);
|
|
||||||
lua_userstateopen(L);
|
|
||||||
return L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API lua_State *lua_open (void) {
|
LUA_API lua_State *lua_open (void) {
|
||||||
lua_State *L;
|
lua_State *L = newthread(NULL);
|
||||||
L = luaM_new(NULL, lua_State);
|
|
||||||
if (L) { /* allocation OK? */
|
if (L) { /* allocation OK? */
|
||||||
preinit_state(L);
|
preinit_state(L);
|
||||||
L->l_G = NULL;
|
L->l_G = NULL;
|
||||||
L->next = L->previous = L;
|
|
||||||
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
||||||
/* memory allocation error: free partial state */
|
/* memory allocation error: free partial state */
|
||||||
close_state(L);
|
close_state(L);
|
||||||
@ -139,14 +150,13 @@ LUA_API lua_State *lua_open (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaE_closethread (lua_State *OL, lua_State *L) {
|
void luaE_freethread (lua_State *L, lua_State *L1) {
|
||||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
luaF_close(L1, L1->stack); /* close all upvalues for this thread */
|
||||||
lua_assert(L->openupval == NULL);
|
lua_assert(L1->openupval == NULL);
|
||||||
L->previous->next = L->next;
|
luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);
|
||||||
L->next->previous = L->previous;
|
luaM_freearray(L, L1->stack, L1->stacksize, TObject);
|
||||||
luaM_freearray(OL, L->base_ci, L->size_ci, CallInfo);
|
luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE,
|
||||||
luaM_freearray(OL, L->stack, L->stacksize, TObject);
|
sizeof(lua_State) + EXTRASPACE);
|
||||||
luaM_freelem(OL, L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,24 +170,15 @@ static void close_state (lua_State *L) {
|
|||||||
luaZ_freebuffer(L, &G(L)->buff);
|
luaZ_freebuffer(L, &G(L)->buff);
|
||||||
luaM_freelem(NULL, L->l_G);
|
luaM_freelem(NULL, L->l_G);
|
||||||
}
|
}
|
||||||
luaE_closethread(NULL, L);
|
luaE_freethread(NULL, L);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API void lua_closethread (lua_State *L, lua_State *thread) {
|
|
||||||
lua_lock(L);
|
|
||||||
if (L == thread) luaG_runerror(L, "cannot close only thread of a state");
|
|
||||||
luaE_closethread(L, thread);
|
|
||||||
lua_unlock(L);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API void lua_close (lua_State *L) {
|
LUA_API void lua_close (lua_State *L) {
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
|
L = G(L)->mainthread; /* only the main thread can be closed */
|
||||||
luaC_callallgcTM(L); /* call GC tag methods for all udata */
|
luaC_callallgcTM(L); /* call GC tag methods for all udata */
|
||||||
lua_assert(G(L)->tmudata == NULL);
|
lua_assert(G(L)->tmudata == NULL);
|
||||||
while (L->next != L) /* then, close all other threads */
|
|
||||||
luaE_closethread(L, L->next);
|
|
||||||
close_state(L);
|
close_state(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
31
lstate.h
31
lstate.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 1.97 2002/10/08 18:46:08 roberto Exp roberto $
|
** $Id: lstate.h,v 1.98 2002/10/22 17:58:14 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -32,12 +32,6 @@
|
|||||||
#define lua_unlock(L) ((void) 0)
|
#define lua_unlock(L) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
** macro to allow the inclusion of user information in Lua state
|
|
||||||
*/
|
|
||||||
#ifndef LUA_USERSTATE
|
|
||||||
#define LUA_USERSTATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef lua_userstateopen
|
#ifndef lua_userstateopen
|
||||||
#define lua_userstateopen(l)
|
#define lua_userstateopen(l)
|
||||||
@ -124,6 +118,7 @@ typedef struct global_State {
|
|||||||
lua_CFunction panic; /* to be called in unprotected errors */
|
lua_CFunction panic; /* to be called in unprotected errors */
|
||||||
TObject _registry;
|
TObject _registry;
|
||||||
TObject _defaultmeta;
|
TObject _defaultmeta;
|
||||||
|
struct lua_State *mainthread;
|
||||||
Node dummynode[1]; /* common node array for all empty tables */
|
Node dummynode[1]; /* common node array for all empty tables */
|
||||||
TString *tmname[TM_N]; /* array with tag-method names */
|
TString *tmname[TM_N]; /* array with tag-method names */
|
||||||
} global_State;
|
} global_State;
|
||||||
@ -133,7 +128,7 @@ typedef struct global_State {
|
|||||||
** `per thread' state
|
** `per thread' state
|
||||||
*/
|
*/
|
||||||
struct lua_State {
|
struct lua_State {
|
||||||
LUA_USERSTATE
|
CommonHeader;
|
||||||
StkId top; /* first free slot in the stack */
|
StkId top; /* first free slot in the stack */
|
||||||
global_State *l_G;
|
global_State *l_G;
|
||||||
CallInfo *ci; /* call info for current function */
|
CallInfo *ci; /* call info for current function */
|
||||||
@ -150,15 +145,29 @@ struct lua_State {
|
|||||||
GCObject *openupval; /* list of open upvalues in this stack */
|
GCObject *openupval; /* list of open upvalues in this stack */
|
||||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
struct lua_longjmp *errorJmp; /* current error recover point */
|
||||||
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
ptrdiff_t errfunc; /* current error handling function (stack index) */
|
||||||
lua_State *next; /* circular double linked list of states */
|
|
||||||
lua_State *previous;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define G(L) (L->l_G)
|
#define G(L) (L->l_G)
|
||||||
|
|
||||||
|
|
||||||
void luaE_closethread (lua_State *OL, lua_State *L);
|
/*
|
||||||
|
** Union of all collectable objects
|
||||||
|
*/
|
||||||
|
union GCObject {
|
||||||
|
GCheader gch;
|
||||||
|
union TString ts;
|
||||||
|
union Udata u;
|
||||||
|
union Closure cl;
|
||||||
|
struct Table h;
|
||||||
|
struct Proto p;
|
||||||
|
struct UpVal uv;
|
||||||
|
struct lua_State th; /* thread */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
lua_State *luaE_newthread (lua_State *L);
|
||||||
|
void luaE_freethread (lua_State *L, lua_State *L1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
7
ltests.c
7
ltests.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltests.c,v 1.136 2002/10/22 17:18:28 roberto Exp roberto $
|
** $Id: ltests.c,v 1.137 2002/10/22 18:07:55 roberto Exp roberto $
|
||||||
** Internal Module for Debugging of the Lua Implementation
|
** Internal Module for Debugging of the Lua Implementation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -403,7 +403,6 @@ static int doonnewstack (lua_State *L) {
|
|||||||
if (status == 0)
|
if (status == 0)
|
||||||
status = lua_pcall(L1, 0, 0, 0);
|
status = lua_pcall(L1, 0, 0, 0);
|
||||||
lua_pushnumber(L, status);
|
lua_pushnumber(L, status);
|
||||||
lua_closethread(L, L1);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +422,7 @@ static int d2s (lua_State *L) {
|
|||||||
static int newstate (lua_State *L) {
|
static int newstate (lua_State *L) {
|
||||||
lua_State *L1 = lua_open();
|
lua_State *L1 = lua_open();
|
||||||
if (L1) {
|
if (L1) {
|
||||||
*cast(int **, L1) = &islocked; /* initialize the lock */
|
lua_userstateopen(L1); /* init lock */
|
||||||
lua_pushnumber(L, (unsigned long)L1);
|
lua_pushnumber(L, (unsigned long)L1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -724,7 +723,7 @@ static void fim (void) {
|
|||||||
|
|
||||||
|
|
||||||
int luaB_opentests (lua_State *L) {
|
int luaB_opentests (lua_State *L) {
|
||||||
*cast(int **, L) = &islocked; /* init lock */
|
lua_userstateopen(L); /* init lock */
|
||||||
lua_state = L; /* keep first state to be opened */
|
lua_state = L; /* keep first state to be opened */
|
||||||
luaL_opennamedlib(L, "T", tests_funcs, 0);
|
luaL_opennamedlib(L, "T", tests_funcs, 0);
|
||||||
atexit(fim);
|
atexit(fim);
|
||||||
|
11
ltests.h
11
ltests.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltests.h,v 1.15 2002/07/17 16:25:13 roberto Exp roberto $
|
** $Id: ltests.h,v 1.16 2002/10/08 18:45:07 roberto Exp roberto $
|
||||||
** Internal Header for Debugging of the Lua Implementation
|
** Internal Header for Debugging of the Lua Implementation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -42,10 +42,11 @@ void *debug_realloc (void *block, size_t oldsize, size_t size);
|
|||||||
|
|
||||||
/* test for lock/unlock */
|
/* test for lock/unlock */
|
||||||
extern int islocked;
|
extern int islocked;
|
||||||
#define LUA_USERSTATE int *lock;
|
#define LUA_USERSTATE int *
|
||||||
#define lua_userstateopen(l) if (l != NULL) *cast(int **, l) = &islocked;
|
#define getlock(l) (*(cast(int **, l) - 1))
|
||||||
#define lua_lock(L) lua_assert((**cast(int **, L))++ == 0)
|
#define lua_userstateopen(l) if (l != NULL) getlock(l) = &islocked;
|
||||||
#define lua_unlock(L) lua_assert(--(**cast(int **, L)) == 0)
|
#define lua_lock(l) lua_assert((*getlock(l))++ == 0)
|
||||||
|
#define lua_unlock(l) lua_assert(--(*getlock(l)) == 0)
|
||||||
|
|
||||||
|
|
||||||
int luaB_opentests (lua_State *L);
|
int luaB_opentests (lua_State *L);
|
||||||
|
4
ltm.c
4
ltm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltm.c,v 1.101 2002/08/30 19:09:21 roberto Exp roberto $
|
** $Id: ltm.c,v 1.102 2002/09/19 20:12:47 roberto Exp roberto $
|
||||||
** Tag methods
|
** Tag methods
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
const char *const luaT_typenames[] = {
|
const char *const luaT_typenames[] = {
|
||||||
"nil", "boolean", "userdata", "number",
|
"nil", "boolean", "userdata", "number",
|
||||||
"string", "table", "function", "userdata"
|
"string", "table", "function", "userdata", "thread"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
5
lua.h
5
lua.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lua.h,v 1.158 2002/10/22 17:18:28 roberto Exp roberto $
|
** $Id: lua.h,v 1.159 2002/10/22 17:21:25 roberto Exp roberto $
|
||||||
** Lua - An Extensible Extension Language
|
** Lua - An Extensible Extension Language
|
||||||
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
||||||
** http://www.lua.org mailto:info@lua.org
|
** http://www.lua.org mailto:info@lua.org
|
||||||
@ -70,6 +70,7 @@ typedef const char * (*lua_Chunkreader) (lua_State *L, void *ud, size_t *sz);
|
|||||||
#define LUA_TTABLE 5
|
#define LUA_TTABLE 5
|
||||||
#define LUA_TFUNCTION 6
|
#define LUA_TFUNCTION 6
|
||||||
#define LUA_TUSERDATA 7
|
#define LUA_TUSERDATA 7
|
||||||
|
#define LUA_TTHREAD 8
|
||||||
|
|
||||||
|
|
||||||
/* minimum Lua stack available to a C function */
|
/* minimum Lua stack available to a C function */
|
||||||
@ -104,7 +105,6 @@ typedef LUA_NUMBER lua_Number;
|
|||||||
LUA_API lua_State *lua_open (void);
|
LUA_API lua_State *lua_open (void);
|
||||||
LUA_API void lua_close (lua_State *L);
|
LUA_API void lua_close (lua_State *L);
|
||||||
LUA_API lua_State *lua_newthread (lua_State *L);
|
LUA_API lua_State *lua_newthread (lua_State *L);
|
||||||
LUA_API void lua_closethread (lua_State *L, lua_State *t);
|
|
||||||
|
|
||||||
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
|
LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
|
||||||
|
|
||||||
@ -142,6 +142,7 @@ LUA_API const char *lua_tostring (lua_State *L, int idx);
|
|||||||
LUA_API size_t lua_strlen (lua_State *L, int idx);
|
LUA_API size_t lua_strlen (lua_State *L, int idx);
|
||||||
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx);
|
LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx);
|
||||||
LUA_API void *lua_touserdata (lua_State *L, int idx);
|
LUA_API void *lua_touserdata (lua_State *L, int idx);
|
||||||
|
LUA_API lua_State *lua_tothread (lua_State *L, int idx);
|
||||||
LUA_API const void *lua_topointer (lua_State *L, int idx);
|
LUA_API const void *lua_topointer (lua_State *L, int idx);
|
||||||
|
|
||||||
|
|
||||||
|
11
lvm.c
11
lvm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 1.256 2002/09/19 20:12:47 roberto Exp roberto $
|
** $Id: lvm.c,v 1.257 2002/10/08 18:46:08 roberto Exp roberto $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -263,23 +263,24 @@ int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {
|
|||||||
switch (ttype(t1)) {
|
switch (ttype(t1)) {
|
||||||
case LUA_TNIL: return 1;
|
case LUA_TNIL: return 1;
|
||||||
case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
|
case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);
|
||||||
case LUA_TSTRING: return tsvalue(t1) == tsvalue(t2);
|
|
||||||
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
|
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
|
||||||
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
|
case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
|
||||||
case LUA_TFUNCTION: return clvalue(t1) == clvalue(t2);
|
case LUA_TUSERDATA: {
|
||||||
case LUA_TUSERDATA:
|
|
||||||
if (uvalue(t1) == uvalue(t2)) return 1;
|
if (uvalue(t1) == uvalue(t2)) return 1;
|
||||||
else if ((tm = fasttm(L, uvalue(t1)->uv.metatable, TM_EQ)) == NULL &&
|
else if ((tm = fasttm(L, uvalue(t1)->uv.metatable, TM_EQ)) == NULL &&
|
||||||
(tm = fasttm(L, uvalue(t2)->uv.metatable, TM_EQ)) == NULL)
|
(tm = fasttm(L, uvalue(t2)->uv.metatable, TM_EQ)) == NULL)
|
||||||
return 0; /* no TM */
|
return 0; /* no TM */
|
||||||
else break; /* will try TM */
|
else break; /* will try TM */
|
||||||
case LUA_TTABLE:
|
}
|
||||||
|
case LUA_TTABLE: {
|
||||||
if (hvalue(t1) == hvalue(t2)) return 1;
|
if (hvalue(t1) == hvalue(t2)) return 1;
|
||||||
else if ((tm = fasttm(L, hvalue(t1)->metatable, TM_EQ)) == NULL &&
|
else if ((tm = fasttm(L, hvalue(t1)->metatable, TM_EQ)) == NULL &&
|
||||||
(tm = fasttm(L, hvalue(t2)->metatable, TM_EQ)) == NULL)
|
(tm = fasttm(L, hvalue(t2)->metatable, TM_EQ)) == NULL)
|
||||||
return 0; /* no TM */
|
return 0; /* no TM */
|
||||||
else break; /* will try TM */
|
else break; /* will try TM */
|
||||||
}
|
}
|
||||||
|
default: return gcvalue(t1) == gcvalue(t2);
|
||||||
|
}
|
||||||
callTMres(L, tm, t1, t2); /* call TM */
|
callTMres(L, tm, t1, t2); /* call TM */
|
||||||
return !l_isfalse(L->top);
|
return !l_isfalse(L->top);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user