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 void (*ReplyHandler_t) (struct Object_s *retValue);
typedef struct Object_s { typedef struct Object_s {
unsigned marked :1;
unsigned finalized :1;
struct Class_s *cl; struct Class_s *cl;
int refs; int refs;
qboolean marked;
struct Object_s *next; struct Object_s *next;
struct String_s * methodDecl(Object, toString); struct String_s * methodDecl(Object, toString);
ObjRefs_t * methodDecl(Object, allRefs); ObjRefs_t * methodDecl(Object, allRefs);
qboolean methodDecl(Object, finalize);
void *data; void *data;
} Object; } Object;

View file

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

View file

@ -61,24 +61,32 @@ Garbage_Do_Mark (Object *root)
} }
} }
void Object *
Garbage_Do_Sweep (Object **allobjs) Garbage_Do_Sweep (Object **allobjs)
{ {
Object **prevNext; Object **prevNext;
Object *obj; Object *obj;
for (prevNext = allobjs, obj = *allobjs; obj; obj = *prevNext) { for (prevNext = allobjs, obj = *allobjs;; obj = *prevNext) {
if (obj->marked) { if (obj->marked) {
obj->marked = false; obj->marked = false;
prevNext = &obj->next; prevNext = &obj->next;
} else if (!obj->refs) { } else if (!obj->refs) {
*prevNext = obj->next; if (!obj->finalized && methodCall(obj, finalize)) {
obj->next = junk; obj->finalized = true;
junk = obj; Garbage_Do_Mark (obj);
junked++; prevNext = &obj->next;
Sys_DPrintf ("GC: %s@%p is ready for disposal...\n", obj->cl->name, obj); } 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 } else
*prevNext = obj->next; *prevNext = obj->next;
if (!*prevNext)
return obj;
} }
} }
@ -89,14 +97,20 @@ Garbage_Pending (void)
} }
void void
Garbage_Dispose (unsigned int amount) Garbage_Dispose (Object **allobjs, unsigned int amount)
{ {
Object *next; Object *next;
for (; junk && amount; junk = next, amount--) { for (; junk && amount; junk = next, amount--) {
next = junk->next; next = junk->next;
Sys_DPrintf ("GC: Disposing of %s@%p...\n", junk->cl->name, junk); if (junk->marked) {
Object_Delete (junk); junk->marked = false;
junked--; 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; Object *allObjs = NULL;
ArrayList *rootObj = NULL; ArrayList *rootObj = NULL;
static qboolean
Object_Finalize_f (Object *self)
{
return false;
}
static String * static String *
Object_ToString_f (Object *self) Object_ToString_f (Object *self)
{ {
@ -72,6 +78,7 @@ Object_Init_f (Object *self)
{ {
self->allRefs = NULL; self->allRefs = NULL;
self->toString = Object_ToString_f; self->toString = Object_ToString_f;
self->finalize = Object_Finalize_f;
Sys_DPrintf("%s@%p initing...\n", self->cl->name, self); Sys_DPrintf("%s@%p initing...\n", self->cl->name, self);
} }
@ -117,6 +124,7 @@ Object_Create (Class *cl, qboolean floating)
} else } else
new->refs = 1; new->refs = 1;
new->marked = false; new->marked = false;
new->finalized = false;
new->next = allObjs; new->next = allObjs;
allObjs = new; allObjs = new;
return new; return new;
@ -243,13 +251,18 @@ Object_Garbage_Collect (void)
frames++; frames++;
if (frames % 2000 == 0) { if (frames % 2000 == 0) {
Object *all, *last;
Sys_DPrintf("GC: Marking...\n"); Sys_DPrintf("GC: Marking...\n");
Garbage_Do_Mark (OBJECT(rootObj)); Garbage_Do_Mark (OBJECT(rootObj));
Sys_DPrintf("GC: Sweeping...\n"); 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()) { if (frames % 50 == 0 && Garbage_Pending()) {
Sys_DPrintf("GC: Disposing...\n"); Sys_DPrintf("GC: Disposing...\n");
Garbage_Dispose (Garbage_Pending()/2 + 1); Garbage_Dispose (&allObjs, Garbage_Pending()/2 + 1);
} }
} }