all collected userdata must go to the end of the list of finalizers

This commit is contained in:
Roberto Ierusalimschy 2005-02-11 18:03:35 -02:00
parent af39352632
commit 678d2fb2ac
2 changed files with 26 additions and 18 deletions

40
lgc.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lgc.c,v 2.22 2005/01/18 17:18:09 roberto Exp roberto $ ** $Id: lgc.c,v 2.23 2005/02/10 13:25:02 roberto Exp roberto $
** Garbage Collector ** Garbage Collector
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -114,21 +114,23 @@ static void reallymarkobject (global_State *g, GCObject *o) {
static void marktmu (global_State *g) { static void marktmu (global_State *g) {
GCObject *u; GCObject *u = g->tmudata;
for (u = g->tmudata; u; u = u->gch.next) { if (u) {
makewhite(g, u); /* may be marked, if left from previous GC */ do {
reallymarkobject(g, u); u = u->gch.next;
makewhite(g, u); /* may be marked, if left from previous GC */
reallymarkobject(g, u);
} while (u != g->tmudata);
} }
} }
/* move `dead' udata that need finalization to list `tmudata' */ /* move `dead' udata that need finalization to list `tmudata' */
size_t luaC_separateudata (lua_State *L, int all) { size_t luaC_separateudata (lua_State *L, int all) {
global_State *g = G(L);
size_t deadmem = 0; size_t deadmem = 0;
GCObject **p = &G(L)->mainthread->next; GCObject **p = &g->mainthread->next;
GCObject *curr; GCObject *curr;
GCObject *collected = NULL; /* to collect udata with gc event */
GCObject **lastcollected = &collected;
while ((curr = *p) != NULL) { while ((curr = *p) != NULL) {
if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
p = &curr->gch.next; /* don't bother with them */ p = &curr->gch.next; /* don't bother with them */
@ -140,14 +142,16 @@ size_t luaC_separateudata (lua_State *L, int all) {
deadmem += sizeudata(gco2u(curr)); deadmem += sizeudata(gco2u(curr));
markfinalized(gco2u(curr)); markfinalized(gco2u(curr));
*p = curr->gch.next; *p = curr->gch.next;
curr->gch.next = NULL; /* link `curr' at the end of `collected' list */ /* link `curr' at the end of `tmudata' list */
*lastcollected = curr; if (g->tmudata == NULL) /* list is empty? */
lastcollected = &curr->gch.next; g->tmudata = curr->gch.next = curr; /* creates a circular list */
else {
curr->gch.next = g->tmudata->gch.next;
g->tmudata->gch.next = curr;
g->tmudata = curr;
}
} }
} }
/* insert collected udata with gc event into `tmudata' list */
*lastcollected = G(L)->tmudata;
G(L)->tmudata = collected;
return deadmem; return deadmem;
} }
@ -443,10 +447,14 @@ static void checkSizes (lua_State *L) {
static void GCTM (lua_State *L) { static void GCTM (lua_State *L) {
global_State *g = G(L); global_State *g = G(L);
GCObject *o = g->tmudata; GCObject *o = g->tmudata->gch.next; /* get first element */
Udata *udata = rawgco2u(o); Udata *udata = rawgco2u(o);
const TValue *tm; const TValue *tm;
g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ /* remove udata from `tmudata' */
if (o == g->tmudata) /* last element? */
g->tmudata = NULL;
else
g->tmudata->gch.next = udata->uv.next;
udata->uv.next = g->mainthread->next; /* return it to `root' list */ udata->uv.next = g->mainthread->next; /* return it to `root' list */
g->mainthread->next = o; g->mainthread->next = o;
makewhite(g, o); makewhite(g, o);

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstate.h,v 2.12 2005/01/14 14:19:42 roberto Exp $ ** $Id: lstate.h,v 2.13 2005/01/18 17:18:09 roberto Exp roberto $
** Global State ** Global State
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -77,7 +77,7 @@ typedef struct global_State {
GCObject *gray; /* list of gray objects */ GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */ GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of weak tables (to be cleared) */ GCObject *weak; /* list of weak tables (to be cleared) */
GCObject *tmudata; /* list of userdata to be GC */ GCObject *tmudata; /* last element of list of userdata to be GC */
Mbuffer buff; /* temporary buffer for string concatentation */ Mbuffer buff; /* temporary buffer for string concatentation */
lu_mem GCthreshold; lu_mem GCthreshold;
lu_mem totalbytes; /* number of bytes currently allocated */ lu_mem totalbytes; /* number of bytes currently allocated */