1
0
mirror of https://github.com/lua/lua.git synced 2025-01-14 05:43:00 +08:00

better implementation of `lua_ref' (much better...)

This commit is contained in:
Roberto Ierusalimschy 1999-11-10 13:37:50 -02:00
parent a7fa7bafc8
commit 53fb65d394
2 changed files with 46 additions and 16 deletions

47
lref.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: $ ** $Id: lref.c,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $
** REF mechanism ** REF mechanism
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -16,31 +16,36 @@ int luaR_ref (const TObject *o, int lock) {
if (ttype(o) == LUA_T_NIL) if (ttype(o) == LUA_T_NIL)
ref = LUA_REFNIL; ref = LUA_REFNIL;
else { else {
for (ref=0; ref<L->refSize; ref++) if (L->refFree != NONEXT) { /* is there a free place? */
if (L->refArray[ref].status == FREE) ref = L->refFree;
break; L->refFree = L->refArray[ref].st;
if (ref == L->refSize) { /* no more empty spaces? */ }
else { /* no more free places */
luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT); 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].o = *o;
L->refArray[ref].status = lock ? LOCK : HOLD; L->refArray[ref].st = lock ? LOCK : HOLD;
} }
return ref; return ref;
} }
void lua_unref (int ref) { void lua_unref (int ref) {
if (ref >= 0 && ref < L->refSize) if (ref >= 0) {
L->refArray[ref].status = FREE; 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) { const TObject *luaR_getref (int ref) {
if (ref == LUA_REFNIL) if (ref == LUA_REFNIL)
return &luaO_nilobject; return &luaO_nilobject;
if (ref >= 0 && ref < L->refSize && else if (0 <= ref && ref < L->refSize &&
(L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD)) (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD))
return &L->refArray[ref].o; return &L->refArray[ref].o;
else else
return NULL; return NULL;
@ -63,16 +68,28 @@ static int ismarked (const TObject *o) {
case LUA_T_CMARK: case LUA_T_PMARK: case LUA_T_CMARK: case LUA_T_PMARK:
LUA_INTERNALERROR("invalid type"); LUA_INTERNALERROR("invalid type");
#endif #endif
default: /* nil, number or cproto */ default: /* number or cproto */
return 1; 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) { void luaR_invalidaterefs (void) {
int n = L->refSize;
int i; int i;
for (i=0; i<L->refSize; i++) for (i=0; i<n; i++) {
if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o)) struct ref *r = &L->refArray[i];
L->refArray[i].status = COLLECTED; 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");
} }

15
lref.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: $ ** $Id: lref.h,v 1.1 1999/10/04 17:50:24 roberto Exp roberto $
** REF mechanism ** REF mechanism
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -9,6 +9,19 @@
#include "lobject.h" #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); int luaR_ref (const TObject *o, int lock);
const TObject *luaR_getref (int ref); const TObject *luaR_getref (int ref);
void luaR_invalidaterefs (void); void luaR_invalidaterefs (void);