diff --git a/lref.c b/lref.c index 2479141c..5c22b63b 100644 --- a/lref.c +++ b/lref.c @@ -1,5 +1,5 @@ /* -** $Id: $ +** $Id: lref.c,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $ ** REF mechanism ** See Copyright Notice in lua.h */ @@ -16,31 +16,36 @@ int luaR_ref (const TObject *o, int lock) { if (ttype(o) == LUA_T_NIL) ref = LUA_REFNIL; else { - for (ref=0; refrefSize; ref++) - if (L->refArray[ref].status == FREE) - break; - if (ref == L->refSize) { /* no more empty spaces? */ + if (L->refFree != NONEXT) { /* is there a free place? */ + ref = L->refFree; + L->refFree = L->refArray[ref].st; + } + else { /* no more free places */ luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); - L->refSize++; + ref = L->refSize++; } L->refArray[ref].o = *o; - L->refArray[ref].status = lock ? LOCK : HOLD; + L->refArray[ref].st = lock ? LOCK : HOLD; } return ref; } void lua_unref (int ref) { - if (ref >= 0 && ref < L->refSize) - L->refArray[ref].status = FREE; + if (ref >= 0) { + if (ref >= L->refSize || L->refArray[ref].st >= 0) + lua_error("API error - invalid parameter for function `lua_unref'"); + L->refArray[ref].st = L->refFree; + L->refFree = ref; + } } const TObject *luaR_getref (int ref) { if (ref == LUA_REFNIL) return &luaO_nilobject; - if (ref >= 0 && ref < L->refSize && - (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD)) + else if (0 <= ref && ref < L->refSize && + (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) return &L->refArray[ref].o; else return NULL; @@ -63,16 +68,28 @@ static int ismarked (const TObject *o) { case LUA_T_CMARK: case LUA_T_PMARK: LUA_INTERNALERROR("invalid type"); #endif - default: /* nil, number or cproto */ + default: /* number or cproto */ return 1; } } +/* for internal debugging only; check if a link of free refs is valid */ +#define VALIDLINK(st,n) (NONEXT <= (st) && (st) < (n)) + void luaR_invalidaterefs (void) { + int n = L->refSize; int i; - for (i=0; irefSize; i++) - if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) - L->refArray[i].status = COLLECTED; + for (i=0; irefArray[i]; + if (r->st == HOLD && !ismarked(&r->o)) + r->st = COLLECTED; + LUA_ASSERT((r->st == LOCK && ismarked(&r->o)) || + r->st == COLLECTED || + r->st == NONEXT || + (r->st < n && VALIDLINK(L->refArray[r->st].st, n)), + "inconsistent ref table"); + } + LUA_ASSERT(VALIDLINK(L->refFree, n), "inconsistent ref table"); } diff --git a/lref.h b/lref.h index 60e14e85..180daab0 100644 --- a/lref.h +++ b/lref.h @@ -1,5 +1,5 @@ /* -** $Id: $ +** $Id: lref.h,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $ ** REF mechanism ** See Copyright Notice in lua.h */ @@ -9,6 +9,19 @@ #include "lobject.h" + +#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) */ +}; + + int luaR_ref (const TObject *o, int lock); const TObject *luaR_getref (int ref); void luaR_invalidaterefs (void);