mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +00:00
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:
parent
e56e566bca
commit
f8baa5be27
4 changed files with 45 additions and 16 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue