Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
125cd8e95d7d527594b3b06c96faadf9eca56f97
[simgrid.git] / tools / tesh2 / src / allocator.c
1
2 #include <allocator.h>
3
4 #include <errno.h>
5 #include <string.h>     /* memset                       */
6 #include <stdlib.h>     /* calloc()     free()  */
7
8
9 static int
10 resize(allocator_t allocator)
11 {
12         allocator_node_t cur, next;
13         allocator_block_t block;
14         int block_capacity, type_size, node_size;
15         register int pos;
16         
17         if(!allocator)
18                 return EINVAL;
19         
20         next = NULL;
21         block_capacity = allocator->block_capacity;
22         type_size = allocator->type_size;
23         node_size = type_size + sizeof(s_allocator_node_t);
24         
25         if(!(block = (allocator_block_t)calloc(1,sizeof(s_allocator_block_t) + (block_capacity * node_size))))
26                 return errno;
27                 
28         /* update the first block of the allocator */
29         block->next = allocator->head;
30         block->allocator = allocator;
31         allocator->head = block;
32         
33         /* move to the last node of the block. */
34         cur = (allocator_node_t)(((byte*)(block + 1)) + ((block_capacity - 1) * node_size));
35         
36         /* initialize all the nodes of the new block */
37         for(pos = block_capacity - 1; pos >= 0; pos--, cur = (allocator_node_t)(((byte*)next) - node_size))
38         {
39                 cur->next = next;
40                 cur->block = block;
41                 next = cur;
42         }
43         
44         /* allocator->free pointed now on the first node of the new bloc. */
45         allocator->free = allocator->first = next;
46         /* update the allocator capacity. */
47         allocator->capacity += block_capacity;
48         
49         return 0;       
50 }
51
52 allocator_t
53 allocator_new(int block_capacity, int type_size, fn_finalize_t fn_finalize)
54 {
55         allocator_t allocator;
56         
57         if((block_capacity <= 0) || (type_size <= 0))
58         {
59                 errno = EINVAL;
60                 return NULL;
61         }
62         
63         if(!(allocator = (allocator_t)calloc(1,sizeof(s_allocator_t))))
64                 return NULL;
65
66         /* updates allocator properties */
67         allocator->block_capacity = block_capacity;
68         allocator->type_size = type_size;
69         
70         /* first block allocation */
71         
72         if(resize(allocator))
73         {
74                 free(allocator);
75                 return NULL;
76         }
77         
78         allocator->fn_finalize = fn_finalize;
79     return allocator;
80 }
81
82 int
83 allocator_free(allocator_t* allocator_ptr)
84 {
85         allocator_block_t cur, next;
86         allocator_node_t node;
87         allocator_t allocator;
88         int pos, node_size;
89         fn_finalize_t fn_finalize;
90         void* type;
91         int rv;
92         
93         if(!(*allocator_ptr))
94                 return EINVAL;
95         
96         
97         allocator = *allocator_ptr;
98         cur = allocator->head;
99         
100         if(allocator->fn_finalize)
101         {
102                 fn_finalize = allocator->fn_finalize;
103                 node_size = allocator->type_size + sizeof(s_allocator_node_t);
104                 
105                 while(cur)
106                 {
107                 
108                         /* type points to the first node */
109                         node = (allocator_node_t)(((byte*)cur) + sizeof(s_allocator_block_t));
110                         
111                         if(node->is_allocated)
112                         {
113                                 type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
114                         
115                                 /* apply the fn_finalize function to the first type */
116                                 
117                                 if((rv = (*fn_finalize)(&type)))
118                                         return rv;
119                         }
120                         
121                         /*clear all the other types */
122                         for(pos = 1; pos < allocator->block_capacity; pos++)
123                         {
124                                 node = (allocator_node_t)(((byte*)node) + node_size);
125                                 
126                                 if(node->is_allocated)
127                                 {
128                                         type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
129                                 
130                                         /* apply the fn_finalize function to the first type */
131                                         
132                                         if((rv = (*fn_finalize)(&type)))
133                                                 return rv;
134                                 }
135                         }
136                         
137                         next = cur->next;
138                         free(cur);
139                         cur = next;
140                 }
141         }
142         else
143         {
144                 while(cur)
145                 {
146                         next = cur->next;
147                         free(cur);
148                         cur = next;
149                 }
150         }
151         
152         free(*allocator_ptr);
153         *allocator_ptr = NULL;
154         
155         return 0;
156 }
157
158 void*
159 allocator_alloc(allocator_t allocator)
160 {
161     allocator_node_t node;
162
163     if(!allocator)
164     {
165         errno = EINVAL;
166         return NULL;
167     }
168     
169         /* all allocator memory is used, allocate a new block */
170         if(!(allocator->free))
171                 if(resize(allocator))
172                         return NULL;
173         
174         node = allocator->free;
175         node->is_allocated = 1;
176         
177         allocator->free  = allocator->free->next;
178         allocator->size++;
179         
180         return (void*)(((byte*)node) + sizeof(s_allocator_node_t));
181 }
182
183 int
184 allocator_dealloc(allocator_t allocator, void* block)
185 {
186         int rv;
187         allocator_node_t node;
188         
189         if(!allocator || !block)
190         return EINVAL;
191         
192         if(allocator->fn_finalize)
193         {
194                 if((rv = (*(allocator->fn_finalize))(&block)))
195                         return rv;
196                         
197                 memset(block, 0, allocator->type_size);
198                 node->is_allocated = 0;
199         }
200         
201         /* get the node address. */
202         node = (allocator_node_t)(((byte*)block) - sizeof(s_allocator_node_t)); 
203         
204         /* the node becomes the free node and the free node become the next free node.*/
205         node->next = allocator->free;
206         allocator->free = node;
207         allocator->size--;
208         
209         return 0;
210 }
211
212 int
213 allocator_get_size(allocator_t allocator)
214 {
215         if(!allocator)
216     {
217         errno = EINVAL;
218         return -1;
219     }
220     
221     return allocator->size;
222 }
223
224 int
225 allocator_get_capacity(allocator_t allocator)
226 {
227         if(!allocator)
228     {
229         errno = EINVAL;
230         return -1;
231     }
232     
233    return allocator->capacity;
234 }
235
236 int
237 allocator_get_type_size(allocator_t allocator)
238 {
239
240         if(NULL == allocator)
241     {
242         errno = EINVAL;
243         return -1;
244     }
245     
246    return allocator->type_size;
247 }
248
249 int
250 allocator_is_empty(allocator_t allocator)
251 {
252         if(NULL == allocator)
253     {
254         errno = EINVAL;
255         return 0;
256     }
257     
258     return !(allocator->size);
259 }
260
261
262 int
263 allocator_is_full(allocator_t allocator)
264 {
265         if(NULL == allocator)
266     {
267         errno = EINVAL;
268         return 0;
269     }
270     
271     return (allocator->size == allocator->capacity);
272 }
273
274 int
275 allocator_get_block_capacity(allocator_t allocator)
276 {
277                 
278         if(!allocator)
279     {
280         errno = EINVAL;
281         return -1;
282     }
283     
284    return allocator->block_capacity;
285 }
286
287 int
288 allocator_get_capacity_available(allocator_t allocator)
289 {
290         if(!allocator)
291     {
292         errno = EINVAL;
293         return -1;
294     }
295     
296         return (allocator->capacity - allocator->size);
297 }
298
299 int
300 allocator_clear(allocator_t allocator)
301 {
302         allocator_block_t cur;
303         allocator_node_t node;
304         
305         int block_capacity, node_size, type_size;
306         fn_finalize_t fn_finalize;
307         void* type;
308         register int pos;
309         int rv;
310         
311         
312         if(!allocator)
313         return EINVAL;
314     
315     
316     if(allocator->fn_finalize)
317         {
318                 fn_finalize = allocator->fn_finalize;
319                 block_capacity = allocator->block_capacity;
320                 type_size = allocator->type_size;
321                 node_size = type_size + sizeof(s_allocator_node_t);
322                 
323                 cur = allocator->head;
324                  
325                 while(cur)
326                 {
327                         /* type points to the first node */
328                         node = (allocator_node_t)(((byte*)cur) + sizeof(s_allocator_block_t));
329                         
330                         if(node->is_allocated)
331                         {
332                         
333                                 type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
334                         
335                                 /* apply the fn_finalize function to the first type */
336                                 
337                                 if((rv = (*fn_finalize)(&type)))
338                                         return rv;
339                                 
340                                 memset(type, 0, type_size);
341                                 node->is_allocated = 0;
342                         }
343                         
344                         /*clear all the other types */
345                         for(pos = 1; pos < block_capacity; pos++)
346                         {
347                                 node = (allocator_node_t)(((byte*)node) + node_size);
348                                 
349                                 if(node->is_allocated)
350                                 {
351                                         type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
352                                 
353                                         /* apply the fn_finalize function to the first type */
354                                         
355                                         if((rv = (*fn_finalize)(&type)))
356                                                 return rv;
357                                 
358                                         memset(type, 0, type_size);
359                                         node->is_allocated = 0;
360                                 }
361                         }
362                 }
363                 
364                 cur = cur->next;
365         }
366         
367     allocator->free = allocator->first;
368     allocator->size = 0;
369     
370     return 0;
371 }