-
Notifications
You must be signed in to change notification settings - Fork 0
/
GarbageCollector.c
144 lines (121 loc) · 3.71 KB
/
GarbageCollector.c
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <stdio.h>
#include <stdlib.h>
typedef struct Object {
int marked; // 0 for not marked, 1 for marked
struct Object** references; // Array of pointers to referenced objects
int num_references; // Number of references
} Object;
typedef struct QueueNode {
Object* obj;
struct QueueNode* next;
} QueueNode;
typedef struct Queue {
QueueNode* front;
QueueNode* rear;
} Queue;
Queue* create_queue() {
Queue* queue = (Queue*)malloc(sizeof(Queue));
queue->front = queue->rear = NULL;
return queue;
}
void enqueue(Queue* queue, Object* obj) {
QueueNode* temp = (QueueNode*)malloc(sizeof(QueueNode));
temp->obj = obj;
temp->next = NULL;
if (queue->rear == NULL) {
queue->front = queue->rear = temp;
return;
}
queue->rear->next = temp;
queue->rear = temp;
}
Object* dequeue(Queue* queue) {
if (queue->front == NULL) return NULL;
QueueNode* temp = queue->front;
queue->front = queue->front->next;
if (queue->front == NULL) queue->rear = NULL;
Object* obj = temp->obj;
free(temp);
return obj;
}
int is_queue_empty(Queue* queue) {
return queue->front == NULL;
}
void destroy_queue(Queue* queue) {
while (!is_queue_empty(queue)) {
dequeue(queue);
}
free(queue);
}
void mark_objects_bfs(Object** roots, int num_roots) {
Queue* queue = create_queue();
// Mark and enqueue all root objects
for (int i = 0; i < num_roots; i++) {
if (roots[i] && roots[i]->marked == 0) {
roots[i]->marked = 1;
enqueue(queue, roots[i]);
}
}
// Perform BFS
while (!is_queue_empty(queue)) {
Object* current = dequeue(queue);
// Traverse all references from the current object
for (int i = 0; i < current->num_references; i++) {
Object* referenced = current->references[i];
if (referenced && referenced->marked == 0) {
referenced->marked = 1;
enqueue(queue, referenced);
}
}
}
destroy_queue(queue);
}
void sweep_objects(Object** objects, int num_objects) {
for (int i = 0; i < num_objects; i++) {
if (objects[i] && objects[i]->marked == 0) {
// Free the object and its references
free(objects[i]->references);
free(objects[i]);
objects[i] = NULL;
} else if (objects[i]) {
// Reset mark for the next collection
objects[i]->marked = 0;
}
}
}
void garbage_collect(Object** roots, int num_roots, Object** all_objects, int num_objects) {
mark_objects_bfs(roots, num_roots);
sweep_objects(all_objects, num_objects);
}
int main() {
// Example objects
Object* obj1 = (Object*)malloc(sizeof(Object));
Object* obj2 = (Object*)malloc(sizeof(Object));
Object* obj3 = (Object*)malloc(sizeof(Object));
// Setting up references
obj1->references = (Object**)malloc(1 * sizeof(Object*));
obj1->references[0] = obj2;
obj1->num_references = 1;
obj1->marked = 0;
obj2->references = (Object**)malloc(1 * sizeof(Object*));
obj2->references[0] = obj3;
obj2->num_references = 1;
obj2->marked = 0;
obj3->references = NULL;
obj3->num_references = 0;
obj3->marked = 0;
// Root objects
Object* roots[] = { obj1 };
Object* all_objects[] = { obj1, obj2, obj3 };
// Perform garbage collection
garbage_collect(roots, 1, all_objects, 3);
// Check which objects were collected
for (int i = 0; i < 3; i++) {
if (all_objects[i] == NULL) {
printf("Object %d was collected.\n", i + 1);
} else {
printf("Object %d is still alive.\n", i + 1);
}
}
return 0;
}