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
** 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; ref<L->refSize; 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; i<L->refSize; i++)
if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o))
L->refArray[i].status = COLLECTED;
for (i=0; i<n; i++) {
struct ref *r = &L->refArray[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");
}

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
** 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);