1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#include "garbage.h"
#define _GARBAGE_ERROR(m) \
ERROR("%s: Garbage error", m);
List *LIST_GARBAGE = NULL;
typedef struct {
void (*p_func)(void*);
void (*p_print)(void*);
int *p_ref_count;
void *p_2free;
GarbageType type;
} _Garbage;
void
garbage_init() {
LIST_GARBAGE = list_new();
}
void
garbage_destroy() {
garbage_collect();
if (!list_empty(LIST_GARBAGE)) {
EPRINTF("The garbage collector still has %d registered items "
" which don't have a zero ref count!\n",
list_size(LIST_GARBAGE));
_GARBAGE_ERROR("Garbage left");
}
list_delete(LIST_GARBAGE);
}
int
garbage_collect() {
ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
List *p_list_garbage_new = list_new();
int i_count = 0;
while (listiterator_has_next(p_iter)) {
_Garbage *p_garbage = listiterator_next(p_iter);
if (p_garbage->p_ref_count == NULL || *p_garbage->p_ref_count <= 0) {
#ifdef DEBUG_GC
printf("DEBUG::GC: Freeing ");
if (NULL != p_garbage->p_print)
(*p_garbage->p_print) (p_garbage->p_2free);
else
printf("0x%x\n", (int) p_garbage->p_2free);
#endif /* DEBUG_GC */
(*p_garbage->p_func) (p_garbage->p_2free);
free(p_garbage);
++i_count;
} else {
list_add_back(p_list_garbage_new, p_garbage);
}
}
listiterator_delete(p_iter);
list_delete(LIST_GARBAGE);
LIST_GARBAGE = p_list_garbage_new;
#ifdef DEBUG_GC
printf("DEBUG::GC: Freed %d items\n", i_count);
#endif /* DEBUG_GC */
return (i_count);
}
void
garbage_add(void *p, GarbageType type) {
garbage_add2(p, free, NULL, type);
}
void
garbage_add2(void *p,
void (*p_func)(void*),
int *p_ref_count,
GarbageType type) {
garbage_add3(p, free, p_func, NULL, type);
}
void
garbage_add3(void *p,
void (*p_func)(void*),
void (*p_print)(void*),
int *p_ref_count,
GarbageType type) {
_Garbage *p_garbage = malloc(sizeof(_Garbage));
p_garbage->p_2free = p;
p_garbage->p_func = p_func;
p_garbage->p_print = p_print;
p_garbage->p_ref_count = p_ref_count;
p_garbage->type = type;
list_add_back(LIST_GARBAGE, p_garbage);
}
void
garbage_add_token(Token *p_token) {
garbage_add3(p_token,
token_delete_cb,
token_print_cb,
&p_token->i_ref_count, GC_TOKEN);
}
|