mirror of https://github.com/lua/lua
re-implementation of refs through weak tables
This commit is contained in:
parent
6473f965ca
commit
beee01b170
80
lapi.c
80
lapi.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lapi.c,v 1.138 2001/04/11 14:42:41 roberto Exp roberto $
|
||||
** $Id: lapi.c,v 1.139 2001/04/11 18:39:37 roberto Exp roberto $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -417,21 +417,18 @@ LUA_API void lua_getglobals (lua_State *L) {
|
|||
|
||||
|
||||
LUA_API int lua_getref (lua_State *L, int ref) {
|
||||
int status = 1;
|
||||
int status;
|
||||
lua_lock(L);
|
||||
if (ref == LUA_REFNIL) {
|
||||
setnilvalue(L->top);
|
||||
api_incr_top(L);
|
||||
status = 1;
|
||||
}
|
||||
else {
|
||||
api_check(L, 0 <= ref && ref < G(L)->nref);
|
||||
if (G(L)->refArray[ref].st != LOCK && G(L)->refArray[ref].st != HOLD)
|
||||
status = 0;
|
||||
else {
|
||||
setobj(L->top, &G(L)->refArray[ref].o);
|
||||
api_incr_top(L);
|
||||
}
|
||||
setobj(L->top, luaH_getnum(G(L)->weakregistry, ref));
|
||||
status = (ttype(L->top) != LUA_TNIL);
|
||||
}
|
||||
if (status)
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return status;
|
||||
}
|
||||
|
@ -445,6 +442,22 @@ LUA_API void lua_newtable (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
LUA_API void lua_getregistry (lua_State *L) {
|
||||
lua_lock(L);
|
||||
sethvalue(L->top, G(L)->registry);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_getweakregistry (lua_State *L) {
|
||||
lua_lock(L);
|
||||
sethvalue(L->top, G(L)->weakregistry);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** set functions (stack -> Lua)
|
||||
|
@ -508,25 +521,26 @@ LUA_API void lua_setglobals (lua_State *L) {
|
|||
|
||||
LUA_API int lua_ref (lua_State *L, int lock) {
|
||||
int ref;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
if (ttype(L->top-1) == LUA_TNIL)
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
ref = LUA_REFNIL;
|
||||
else {
|
||||
if (G(L)->refFree != NONEXT) { /* is there a free place? */
|
||||
ref = G(L)->refFree;
|
||||
G(L)->refFree = G(L)->refArray[ref].st;
|
||||
}
|
||||
else { /* no more free places */
|
||||
luaM_growvector(L, G(L)->refArray, G(L)->nref, G(L)->sizeref, struct Ref,
|
||||
MAX_INT, l_s("reference table overflow"));
|
||||
ref = G(L)->nref++;
|
||||
}
|
||||
setobj(&G(L)->refArray[ref].o, L->top-1);
|
||||
G(L)->refArray[ref].st = lock ? LOCK : HOLD;
|
||||
}
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
else {
|
||||
lua_getweakregistry(L);
|
||||
ref = lua_getn(L, -1) + 1;
|
||||
lua_pushvalue(L, -2);
|
||||
lua_rawseti(L, -2, ref);
|
||||
if (lock) {
|
||||
lua_getregistry(L);
|
||||
lua_pushvalue(L, -3);
|
||||
lua_rawseti(L, -2, ref);
|
||||
lua_pop(L, 1); /* remove registry */
|
||||
}
|
||||
lua_pushliteral(L, "n");
|
||||
lua_pushnumber(L, ref);
|
||||
lua_settable(L, -3);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
@ -671,13 +685,15 @@ LUA_API void lua_error (lua_State *L, const l_char *s) {
|
|||
|
||||
|
||||
LUA_API void lua_unref (lua_State *L, int ref) {
|
||||
lua_lock(L);
|
||||
if (ref >= 0) {
|
||||
api_check(L, ref < G(L)->nref && G(L)->refArray[ref].st < 0);
|
||||
G(L)->refArray[ref].st = G(L)->refFree;
|
||||
G(L)->refFree = ref;
|
||||
lua_getregistry(L);
|
||||
lua_pushnil(L);
|
||||
lua_rawseti(L, -2, ref);
|
||||
lua_getweakregistry(L);
|
||||
lua_pushnil(L);
|
||||
lua_rawseti(L, -2, ref);
|
||||
lua_pop(L, 2); /* remove both registries */
|
||||
}
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
|
|
35
lgc.c
35
lgc.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 roberto Exp roberto $
|
||||
** $Id: lgc.c,v 1.96 2001/04/11 14:42:41 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -111,15 +111,6 @@ static void markstacks (lua_State *L, GCState *st) {
|
|||
}
|
||||
|
||||
|
||||
static void marklock (global_State *G, GCState *st) {
|
||||
int i;
|
||||
for (i=0; i<G->nref; i++) {
|
||||
if (G->refArray[i].st == LOCK)
|
||||
markobject(st, &G->refArray[i].o);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void marktagmethods (global_State *G, GCState *st) {
|
||||
int t;
|
||||
for (t=0; t<G->ntag; t++) {
|
||||
|
@ -176,8 +167,9 @@ static void markall (lua_State *L) {
|
|||
st.tmark = NULL;
|
||||
marktagmethods(G(L), &st); /* mark tag methods */
|
||||
markstacks(L, &st); /* mark all stacks */
|
||||
marklock(G(L), &st); /* mark locked objects */
|
||||
marktable(&st, G(L)->type2tag);
|
||||
marktable(&st, G(L)->registry);
|
||||
marktable(&st, G(L)->weakregistry);
|
||||
for (;;) { /* mark tables and closures */
|
||||
if (st.cmark) {
|
||||
Closure *f = st.cmark; /* get first closure from list */
|
||||
|
@ -208,26 +200,6 @@ static int hasmark (const TObject *o) {
|
|||
}
|
||||
|
||||
|
||||
/* macro for internal debugging; check if a link of free refs is valid */
|
||||
#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
|
||||
|
||||
static void invalidaterefs (global_State *G) {
|
||||
int n = G->nref;
|
||||
int i;
|
||||
for (i=0; i<n; i++) {
|
||||
struct Ref *r = &G->refArray[i];
|
||||
if (r->st == HOLD && !hasmark(&r->o))
|
||||
r->st = COLLECTED;
|
||||
lua_assert((r->st == LOCK && hasmark(&r->o)) ||
|
||||
(r->st == HOLD && hasmark(&r->o)) ||
|
||||
r->st == COLLECTED ||
|
||||
r->st == NONEXT ||
|
||||
(r->st < n && VALIDLINK(L, G->refArray[r->st].st, n)));
|
||||
}
|
||||
lua_assert(VALIDLINK(L, G->refFree, n));
|
||||
}
|
||||
|
||||
|
||||
static void invalidatetable (Hash *h) {
|
||||
int i;
|
||||
for (i=0; i<h->size; i++) {
|
||||
|
@ -408,7 +380,6 @@ void luaC_collect (lua_State *L, int all) {
|
|||
|
||||
void luaC_collectgarbage (lua_State *L) {
|
||||
markall(L);
|
||||
invalidaterefs(G(L)); /* check unlocked references */
|
||||
invalidatetables(G(L));
|
||||
luaC_collect(L, 0);
|
||||
checkMbuffer(L);
|
||||
|
|
25
lstate.c
25
lstate.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.c,v 1.60 2001/03/09 18:05:05 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 1.61 2001/03/26 14:31:49 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -29,20 +29,6 @@ struct Sopen {
|
|||
static void close_state (lua_State *L, lua_State *OL);
|
||||
|
||||
|
||||
/*
|
||||
** initialize ref array and registry
|
||||
*/
|
||||
#define INIT_REFSIZE 4
|
||||
|
||||
static void ref_init (lua_State *L) {
|
||||
G(L)->refArray = luaM_newvector(L, INIT_REFSIZE, struct Ref);
|
||||
G(L)->sizeref = INIT_REFSIZE;
|
||||
sethvalue(&G(L)->refArray[0].o, luaH_new(L, 0));
|
||||
G(L)->refArray[0].st = LOCK;
|
||||
G(L)->nref = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** open parts that may cause memory-allocation errors
|
||||
*/
|
||||
|
@ -74,18 +60,16 @@ static void f_luaopen (lua_State *L, void *ud) {
|
|||
G(L)->TMtable = NULL;
|
||||
G(L)->sizeTM = 0;
|
||||
G(L)->ntag = 0;
|
||||
G(L)->refArray = NULL;
|
||||
G(L)->nref = 0;
|
||||
G(L)->sizeref = 0;
|
||||
G(L)->refFree = NONEXT;
|
||||
G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
|
||||
luaD_init(L, so->stacksize); /* init stack */
|
||||
L->gt = luaH_new(L, 10); /* table of globals */
|
||||
G(L)->type2tag = luaH_new(L, 10);
|
||||
G(L)->registry = luaH_new(L, 0);
|
||||
G(L)->weakregistry = luaH_new(L, 0);
|
||||
G(L)->weakregistry->weakmode = LUA_WEAK_VALUE; /* make weakregistry weak */
|
||||
luaS_init(L);
|
||||
luaX_init(L);
|
||||
luaT_init(L);
|
||||
ref_init(L);
|
||||
G(L)->GCthreshold = 4*G(L)->nblocks;
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +117,6 @@ static void close_state (lua_State *L, lua_State *OL) {
|
|||
lua_assert(G(L)->roottable == NULL);
|
||||
luaS_freeall(L);
|
||||
luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
|
||||
luaM_freearray(L, G(L)->refArray, G(L)->sizeref, struct Ref);
|
||||
luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char);
|
||||
luaM_freelem(NULL, L->G, global_State);
|
||||
}
|
||||
|
|
22
lstate.h
22
lstate.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.h,v 1.54 2001/03/02 17:27:50 roberto Exp roberto $
|
||||
** $Id: lstate.h,v 1.55 2001/03/07 18:09:25 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -32,20 +32,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** marks for Reference array
|
||||
*/
|
||||
#define NONEXT -1 /* to end the free list */
|
||||
#define HOLD -2
|
||||
#define COLLECTED -3
|
||||
#define LOCK -4
|
||||
|
||||
|
||||
struct Ref {
|
||||
TObject o;
|
||||
int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */
|
||||
};
|
||||
|
||||
|
||||
struct lua_longjmp; /* defined in ldo.c */
|
||||
struct TM; /* defined in ltm.h */
|
||||
|
@ -70,13 +56,11 @@ typedef struct global_State {
|
|||
stringtable strt; /* hash table for strings */
|
||||
stringtable udt; /* hash table for udata */
|
||||
Hash *type2tag; /* hash table from type names to tags */
|
||||
Hash *registry; /* (strong) registry table */
|
||||
Hash *weakregistry; /* weakregistry table */
|
||||
struct TM *TMtable; /* table for tag methods */
|
||||
int sizeTM; /* size of TMtable */
|
||||
int ntag; /* number of tags in TMtable */
|
||||
struct Ref *refArray; /* locked objects */
|
||||
int nref; /* first unused element in refArray */
|
||||
int sizeref; /* size of refArray */
|
||||
int refFree; /* list of free positions in refArray */
|
||||
lu_mem GCthreshold;
|
||||
lu_mem nblocks; /* number of `bytes' currently allocated */
|
||||
} global_State;
|
||||
|
|
15
ltests.c
15
ltests.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltests.c,v 1.77 2001/03/26 14:31:49 roberto Exp roberto $
|
||||
** $Id: ltests.c,v 1.78 2001/04/11 14:42:41 roberto Exp roberto $
|
||||
** Internal Module for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -383,21 +383,30 @@ static int string_query (lua_State *L) {
|
|||
|
||||
|
||||
static int tref (lua_State *L) {
|
||||
int level = lua_gettop(L);
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushvalue(L, 1);
|
||||
lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1)));
|
||||
assert(lua_gettop(L) == level+1); /* +1 for result */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int getref (lua_State *L) {
|
||||
if (lua_getref(L, luaL_check_int(L, 1)))
|
||||
int level = lua_gettop(L);
|
||||
if (lua_getref(L, luaL_check_int(L, 1))) {
|
||||
assert(lua_gettop(L) == level+1);
|
||||
return 1;
|
||||
else
|
||||
}
|
||||
else {
|
||||
assert(lua_gettop(L) == level);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int unref (lua_State *L) {
|
||||
int level = lua_gettop(L);
|
||||
lua_unref(L, luaL_check_int(L, 1));
|
||||
assert(lua_gettop(L) == level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
25
lua.h
25
lua.h
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
** $Id: lua.h,v 1.94 2001/04/11 14:42:41 roberto Exp roberto $
|
||||
** $Id: lua.h,v 1.95 2001/04/11 18:39:37 roberto Exp roberto $
|
||||
** Lua - An Extensible Extension Language
|
||||
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
|
||||
** e-mail: lua@tecgraf.puc-rio.br
|
||||
** e-mail: info@lua.org
|
||||
** www: http://www.lua.org
|
||||
** See Copyright Notice at the end of this file
|
||||
*/
|
||||
|
@ -29,24 +29,20 @@
|
|||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
#define LUA_REFREGISTRY 0
|
||||
|
||||
/* pre-defined tags */
|
||||
#define LUA_NOTAG (-2)
|
||||
|
||||
|
||||
/* option for multiple returns in lua_call */
|
||||
/* option for multiple returns in `lua_call' */
|
||||
#define LUA_MULTRET (-1)
|
||||
|
||||
|
||||
/* error codes for lua_do* */
|
||||
/* error codes for `lua_do*' and the like */
|
||||
#define LUA_ERRRUN 1
|
||||
#define LUA_ERRFILE 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
|
||||
/* weak modes */
|
||||
/* weak-table modes */
|
||||
#define LUA_WEAK_KEY 1
|
||||
#define LUA_WEAK_VALUE 2
|
||||
|
||||
|
@ -67,6 +63,11 @@ typedef int (*lua_CFunction) (lua_State *L);
|
|||
#define LUA_TTABLE 4
|
||||
#define LUA_TFUNCTION 5
|
||||
|
||||
/*
|
||||
** an invalid `tag'
|
||||
*/
|
||||
#define LUA_NOTAG (-2)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
@ -77,7 +78,7 @@ typedef int (*lua_CFunction) (lua_State *L);
|
|||
#endif
|
||||
|
||||
|
||||
/* minimum stack available for a C function */
|
||||
/* minimum Lua stack available to a C function */
|
||||
#define LUA_MINSTACK 20
|
||||
|
||||
|
||||
|
@ -163,6 +164,8 @@ LUA_API void lua_getglobals (lua_State *L);
|
|||
LUA_API void lua_gettagmethod (lua_State *L, int tag, const lua_char *event);
|
||||
LUA_API int lua_getref (lua_State *L, int ref);
|
||||
LUA_API void lua_newtable (lua_State *L);
|
||||
LUA_API void lua_getregistry (lua_State *L);
|
||||
LUA_API void lua_getweakregistry (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -241,8 +244,6 @@ LUA_API int lua_getweakmode (lua_State *L, int index);
|
|||
#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL)
|
||||
#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE)
|
||||
|
||||
#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY)
|
||||
|
||||
#define lua_pushliteral(L, s) lua_pushlstring(L, s, \
|
||||
(sizeof(s)/sizeof(lua_char))-1)
|
||||
|
||||
|
|
Loading…
Reference in New Issue