mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-29 23:52:22 +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 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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
if (!obj->finalized && methodCall(obj, finalize)) {
|
||||||
|
obj->finalized = true;
|
||||||
|
Garbage_Do_Mark (obj);
|
||||||
|
prevNext = &obj->next;
|
||||||
|
} else {
|
||||||
*prevNext = obj->next;
|
*prevNext = obj->next;
|
||||||
obj->next = junk;
|
obj->next = junk;
|
||||||
junk = obj;
|
junk = obj;
|
||||||
junked++;
|
junked++;
|
||||||
Sys_DPrintf ("GC: %s@%p is ready for disposal...\n", obj->cl->name, obj);
|
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;
|
||||||
|
if (junk->marked) {
|
||||||
|
junk->marked = false;
|
||||||
|
junk->next = *allobjs;
|
||||||
|
*allobjs = junk;
|
||||||
|
} else {
|
||||||
Sys_DPrintf ("GC: Disposing of %s@%p...\n", junk->cl->name, junk);
|
Sys_DPrintf ("GC: Disposing of %s@%p...\n", junk->cl->name, junk);
|
||||||
Object_Delete (junk);
|
Object_Delete (junk);
|
||||||
junked--;
|
junked--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue