-
Notifications
You must be signed in to change notification settings - Fork 0
/
garbage.c
149 lines (115 loc) · 3.45 KB
/
garbage.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
145
146
147
148
149
#include "garbage.h"
void gc_delete_last(){
if(garbage->First != NULL){ /*Non-empty list*/
if(garbage->Last == garbage->Active){
garbage->Active = NULL;
}
tDLElemPtr temp;
if(garbage->First == garbage->Last){ /*Just one element in list*/
free(garbage->First);
garbage->First=NULL;
garbage->Last=NULL;
}
else{ /*Two or more elements in list*/
temp=garbage->Last->lptr;
free(garbage->Last);
garbage->Last=temp;
garbage->Last->rptr=NULL;
}
}
}
void gc_insert_last(void *data){
tDLElemPtr new = malloc(sizeof(struct tDLElem));
if (new == NULL){
gc_free_all(); //free all
fprintf(stderr,"INTERNAL ERROR: malloc failed");
exit(99);
}
else{
new->data=data;
if(garbage->First == NULL){ //Empty list
garbage->First=new;
garbage->Last=new;
new->rptr=NULL;
new->lptr=NULL;
}
else { //One or more elements in list
new->lptr=garbage->Last;
garbage->Last->rptr=new;
new->rptr=NULL;
garbage->Last=new;
}
}
}
void gc_delete_element(void *element){
tDLElemPtr temp = garbage->Last;
while(temp != NULL){
if(temp == element){ //delete this one
if(temp->rptr != NULL && temp->lptr != NULL){
temp->rptr->lptr = temp->lptr;
temp->lptr->rptr = temp->rptr;
}
else if(temp->rptr != NULL){
temp->rptr->lptr = temp->lptr;
garbage->First = temp->rptr;
}
else if(temp->lptr != NULL){
temp->lptr->rptr = temp->rptr;
garbage->Last = temp->lptr;
}
free(temp);
break;
}
else{
temp = temp->lptr;
}
}
}
void *gc_malloc(size_t size){
void *ptr = malloc(size);
if(ptr == NULL){
gc_free_all(); //free all
fprintf(stderr,"INTERNAL ERROR: malloc failed");
exit(99);
}
gc_insert_last(ptr); //if failed, exits in gc_insert_last func
return ptr;
}
void *gc_realloc(void *ptr, size_t size){
void *temp = ptr;
//realloc feature size = 0, is for now not implemented
ptr = realloc(ptr, size);
if(ptr == NULL){
//deletes origin pointer from log,
// but it won't be freed, cause, it is maybe already freed by realloc
gc_delete_element(find(temp));
gc_free_all(); //free all
fprintf(stderr,"INTERNAL ERROR: malloc failed");
exit(99);
}
if(ptr != temp){
if(temp != NULL){ gc_delete_element(find(temp)); } //remove and free from log
gc_insert_last(ptr); //if failed, exits in gc_insert_last func
}
return ptr;
}
void gc_free(void *ptr){
free(ptr); //free usefull data
gc_delete_element(find(ptr)); //remove and free from log
}
void *find(void *ptr){
tDLElemPtr temp = garbage->Last;
while(temp != NULL){
if(temp->data == ptr){
return temp;
}
temp = temp->lptr;
}
return NULL;
}
void gc_free_all(){
while( copy_last(garbage) != NULL ){
free(copy_last(garbage)); //free usefull data
gc_delete_last(); //free structure from G
}
}