Added a finalize method to all Objects and modified the garbage

collector to deal with objects that might gain references during
finalization.
This commit is contained in:
Brian Koropoff 2003-12-09 06:57:35 +00:00
parent e56e566bca
commit f8baa5be27
4 changed files with 45 additions and 16 deletions

View file

@ -74,12 +74,14 @@ struct List_s;
typedef void (*ReplyHandler_t) (struct Object_s *retValue);
typedef struct Object_s {
unsigned marked :1;
unsigned finalized :1;
struct Class_s *cl;
int refs;
qboolean marked;
struct Object_s *next;
struct String_s * methodDecl(Object, toString);
ObjRefs_t * methodDecl(Object, allRefs);
qboolean methodDecl(Object, finalize);
void *data;
} Object;

View file

@ -33,8 +33,8 @@
#define __garbage_h
void Garbage_Do_Mark (Object *root);
void Garbage_Do_Sweep (Object **allobjs);
Object * Garbage_Do_Sweep (Object **allobjs);
unsigned int Garbage_Pending (void);
void Garbage_Dispose (unsigned int amount);
void Garbage_Dispose (Object **allobjs, unsigned int amount);
#endif

View file

@ -61,24 +61,32 @@ Garbage_Do_Mark (Object *root)
}
}
void
Object *
Garbage_Do_Sweep (Object **allobjs)
{
Object **prevNext;
Object *obj;
for (prevNext = allobjs, obj = *allobjs; obj; obj = *prevNext) {
for (prevNext = allobjs, obj = *allobjs;; obj = *prevNext) {
if (obj->marked) {
obj->marked = false;
prevNext = &obj->next;
} else if (!obj->refs) {
*prevNext = obj->next;
obj->next = junk;
junk = obj;
junked++;
Sys_DPrintf ("GC: %s@%p is ready for disposal...\n", obj->cl->name, obj);
if (!obj->finalized && methodCall(obj, finalize)) {
obj->finalized = true;
Garbage_Do_Mark (obj);
prevNext = &obj->next;
} else {
*prevNext = obj->next;
obj->next = junk;
junk = obj;
junked++;
Sys_DPrintf ("GC: %s@%p is ready for disposal...\n", obj->cl->name, obj);
}
} else
*prevNext = obj->next;
if (!*prevNext)
return obj;
}
}
@ -89,14 +97,20 @@ Garbage_Pending (void)
}
void
Garbage_Dispose (unsigned int amount)
Garbage_Dispose (Object **allobjs, unsigned int amount)
{
Object *next;
for (; junk && amount; junk = next, amount--) {
next = junk->next;
Sys_DPrintf ("GC: Disposing of %s@%p...\n", junk->cl->name, junk);
Object_Delete (junk);
junked--;
if (junk->marked) {
junk->marked = false;
junk->next = *allobjs;
*allobjs = junk;
} else {
Sys_DPrintf ("GC: Disposing of %s@%p...\n", junk->cl->name, junk);
Object_Delete (junk);
junked--;
}
}
}

View file

@ -61,6 +61,12 @@ static __attribute__ ((unused)) const char rcsid[] =
Object *allObjs = NULL;
ArrayList *rootObj = NULL;
static qboolean
Object_Finalize_f (Object *self)
{
return false;
}
static String *
Object_ToString_f (Object *self)
{
@ -72,6 +78,7 @@ Object_Init_f (Object *self)
{
self->allRefs = NULL;
self->toString = Object_ToString_f;
self->finalize = Object_Finalize_f;
Sys_DPrintf("%s@%p initing...\n", self->cl->name, self);
}
@ -117,6 +124,7 @@ Object_Create (Class *cl, qboolean floating)
} else
new->refs = 1;
new->marked = false;
new->finalized = false;
new->next = allObjs;
allObjs = new;
return new;
@ -243,13 +251,18 @@ Object_Garbage_Collect (void)
frames++;
if (frames % 2000 == 0) {
Object *all, *last;
Sys_DPrintf("GC: Marking...\n");
Garbage_Do_Mark (OBJECT(rootObj));
Sys_DPrintf("GC: Sweeping...\n");
Garbage_Do_Sweep (&allObjs);
all = allObjs;
allObjs = NULL;
last = Garbage_Do_Sweep (&all);
last->next = allObjs;
allObjs = all;
}
if (frames % 50 == 0 && Garbage_Pending()) {
Sys_DPrintf("GC: Disposing...\n");
Garbage_Dispose (Garbage_Pending()/2 + 1);
Garbage_Dispose (&allObjs, Garbage_Pending()/2 + 1);
}
}