garbage collector implemented but untested. Also unsused because the issue is

WHEN to call it. I don't imagine it will be cheap :/
This commit is contained in:
Bill Currie 2001-03-06 05:29:46 +00:00
parent 4489319298
commit 97bf8d2c51
2 changed files with 49 additions and 11 deletions

View file

@ -196,7 +196,7 @@ struct progs_s {
// garbage collected strings // garbage collected strings
strref_t *static_strings; strref_t *static_strings;
strref_t dynamic_strings[2]; // 0 = head, 1 = tail strref_t dynamic_strings; // head of linked list;
struct hashtab_s *strref_hash; struct hashtab_s *strref_hash;
int num_strings; int num_strings;

View file

@ -59,7 +59,8 @@ strref_free (void *_sr, void *_pr)
if (sr < pr->static_strings || sr >= pr->static_strings + pr->num_strings) { if (sr < pr->static_strings || sr >= pr->static_strings + pr->num_strings) {
free (sr->string); free (sr->string);
sr->next->prev = sr->prev; if (sr->next)
sr->next->prev = sr->prev;
sr->prev->next = sr->next; sr->prev->next = sr->next;
free (sr); free (sr);
@ -83,10 +84,8 @@ PR_LoadStrings (progs_t *pr)
pr->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, pr); pr->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, pr);
} }
pr->dynamic_strings[0].next = &pr->dynamic_strings[1]; pr->dynamic_strings.next = 0;
pr->dynamic_strings[0].prev = 0; pr->dynamic_strings.prev = 0;
pr->dynamic_strings[1].next = 0;
pr->dynamic_strings[1].prev = &pr->dynamic_strings[1];
if (pr->static_strings) if (pr->static_strings)
free (pr->static_strings); free (pr->static_strings);
@ -102,6 +101,42 @@ PR_LoadStrings (progs_t *pr)
pr->num_strings = count; pr->num_strings = count;
} }
void
PR_GarbageCollect (progs_t *pr)
{
strref_t *sr;
ddef_t *def;
int i, j;
for (sr = pr->dynamic_strings.next; sr; sr = sr->next)
sr->count = 0;
for (i = 0; i < pr->progs->numglobaldefs; i++) {
def = &pr->pr_globaldefs[i];
if ((def->type & ~DEF_SAVEGLOBAL) == ev_string) {
sr = Hash_Find (pr->strref_hash, G_STRING (pr, def->ofs));
if (sr)
sr->count++;
}
}
for (i = 0; i < pr->progs->numfielddefs; i++) {
def = &pr->pr_fielddefs[i];
if ((def->type & ~DEF_SAVEGLOBAL) == ev_string) {
for (j = 0; j < *pr->num_edicts; j++) {
sr = Hash_Find (pr->strref_hash,
E_STRING (pr, EDICT_NUM (pr, j), def->ofs));
if (sr)
sr->count++;
}
}
}
for (sr = pr->dynamic_strings.next; sr; sr = sr->next) {
if (sr->count) {
Hash_Del (pr->strref_hash, sr->string);
strref_free (sr, pr);
}
}
}
char * char *
PR_GetString (progs_t *pr, int num) PR_GetString (progs_t *pr, int num)
{ {
@ -120,11 +155,14 @@ PR_SetString (progs_t *pr, char *s)
sr->string = strdup(s); sr->string = strdup(s);
sr->count = 0; sr->count = 0;
sr->next = pr->dynamic_strings[0].next; sr->next = pr->dynamic_strings.next;
sr->prev = pr->dynamic_strings[0].next->prev; if (pr->dynamic_strings.next) {
sr->prev = pr->dynamic_strings.next->prev;
pr->dynamic_strings[0].next->prev = sr; pr->dynamic_strings.next->prev = sr;
pr->dynamic_strings[0].next = sr; } else {
sr->prev = &pr->dynamic_strings;
}
pr->dynamic_strings.next = sr;
Hash_Add (pr->strref_hash, sr); Hash_Add (pr->strref_hash, sr);