new API for weak mode
This commit is contained in:
63
lgc.c
63
lgc.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id: lgc.c,v 1.143 2002/07/17 16:25:13 roberto Exp $
|
||||
** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -35,12 +35,6 @@ typedef struct GCState {
|
||||
#define ismarked(x) ((x)->mark != (x))
|
||||
|
||||
|
||||
/* `Table.flag' bits to indicate whether table is key-weak and/or value-weak */
|
||||
#define KEYWEAKBIT (TM_MODE+1) /* ORDER TM */
|
||||
#define VALUEWEAKBIT (TM_MODE+2)
|
||||
#define KEYWEAK (1<<KEYWEAKBIT)
|
||||
#define VALUEWEAK (1<<VALUEWEAKBIT)
|
||||
|
||||
|
||||
/* mark tricks for userdata */
|
||||
#define isudmarked(u) (u->uv.len & 1)
|
||||
@@ -221,19 +215,15 @@ static void removekey (Node *n) {
|
||||
|
||||
static void traversetable (GCState *st, Table *h) {
|
||||
int i;
|
||||
const TObject *mode;
|
||||
int weakkey = 0;
|
||||
int weakvalue = 0;
|
||||
marktable(st, h->metatable);
|
||||
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
|
||||
mode = fasttm(st->L, h->metatable, TM_MODE);
|
||||
if (mode && ttisstring(mode)) { /* weak table? */
|
||||
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
|
||||
weakkey = h->mode & WEAKKEY;
|
||||
weakvalue = h->mode & WEAKVALUE;
|
||||
h->mark = st->toclear; /* must be cleared after GC, ... */
|
||||
st->toclear = h; /* ...put in the appropriate list */
|
||||
weakkey = (strchr(svalue(mode), 'k') != NULL);
|
||||
weakvalue = (strchr(svalue(mode), 'v') != NULL);
|
||||
h->flags &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
|
||||
h->flags |= (weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT);
|
||||
st->toclear = h; /* ... so put in the appropriate list */
|
||||
}
|
||||
if (!weakvalue) {
|
||||
i = sizearray(h);
|
||||
@@ -284,14 +274,14 @@ static int hasmark (const TObject *o) {
|
||||
static void cleartablekeys (GCState *st) {
|
||||
Table *h;
|
||||
for (h = st->toclear; h; h = h->mark) {
|
||||
int i;
|
||||
if (!(h->flags & KEYWEAK)) continue;
|
||||
lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'k'));
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(key(n)))
|
||||
removekey(n); /* ... and key */
|
||||
lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
|
||||
if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
|
||||
int i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(key(n))) /* key was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,20 +293,19 @@ static void cleartablekeys (GCState *st) {
|
||||
static void cleartablevalues (GCState *st) {
|
||||
Table *h;
|
||||
for (h = st->toclear; h; h = h->mark) {
|
||||
int i;
|
||||
if (!(h->flags & VALUEWEAK)) continue;
|
||||
lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'v'));
|
||||
i = sizearray(h);
|
||||
while (i--) {
|
||||
TObject *o = &h->array[i];
|
||||
if (!hasmark(o))
|
||||
setnilvalue(o); /* remove value */
|
||||
}
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(val(n)))
|
||||
removekey(n); /* ... and key */
|
||||
if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
|
||||
int i = sizearray(h);
|
||||
while (i--) {
|
||||
TObject *o = &h->array[i];
|
||||
if (!hasmark(o)) /* value was collected? */
|
||||
setnilvalue(o); /* remove value */
|
||||
}
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = node(h, i);
|
||||
if (!hasmark(val(n))) /* value was collected? */
|
||||
removekey(n); /* remove entry from table */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user