Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
tesh version 2
[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((errno = 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         
92         if(!(*allocator_ptr))
93                 return EINVAL;
94         
95         
96         allocator = *allocator_ptr;
97         cur = allocator->head;
98         
99         if(allocator->fn_finalize)
100         {
101                 fn_finalize = allocator->fn_finalize;
102                 node_size = allocator->type_size + sizeof(s_allocator_node_t);
103                 
104                 while(cur)
105                 {
106                 
107                         /* type points to the first node */
108                         node = (allocator_node_t)(((byte*)cur) + sizeof(s_allocator_block_t));
109                         
110                         if(node->is_allocated)
111                         {
112                                 type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
113                         
114                                 /* apply the fn_finalize function to the first type */
115                                 
116                                 if((errno = (*fn_finalize)(&type)))
117                                         return errno;
118                         }
119                         
120                         /*clear all the other types */
121                         for(pos = 1; pos < allocator->block_capacity; pos++)
122                         {
123                                 node = (allocator_node_t)(((byte*)node) + node_size);
124                                 
125                                 if(node->is_allocated)
126                                 {
127                                         type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
128                                 
129                                         /* apply the fn_finalize function to the first type */
130                                         
131                                         if((errno = (*fn_finalize)(&type)))
132                                                 return errno;
133                                 }
134                         }
135                         
136                         next = cur->next;
137                         free(cur);
138                         cur = next;
139                 }
140         }
141         else
142         {
143                 while(cur)
144                 {
145                         next = cur->next;
146                         free(cur);
147                         cur = next;
148                 }
149         }
150         
151         free(*allocator_ptr);
152         *allocator_ptr = NULL;
153         
154         return 0;
155 }
156
157 void*
158 allocator_alloc(allocator_t allocator)
159 {
160     allocator_node_t node;
161
162     if(!allocator)
163     {
164         errno = EINVAL;
165         return NULL;
166     }
167     
168         /* all allocator memory is used, allocate a new block */
169         if(!(allocator->free))
170                 if(resize(allocator))
171                         return NULL;
172         
173         node = allocator->free;
174         node->is_allocated = 1;
175         
176         allocator->free  = allocator->free->next;
177         allocator->size++;
178         
179         return (void*)(((byte*)node) + sizeof(s_allocator_node_t));
180 }
181
182 int
183 allocator_dealloc(allocator_t allocator, void* block)
184 {
185         allocator_node_t node;
186         
187         if(!allocator || !block)
188         return EINVAL;
189         
190         if(allocator->fn_finalize)
191         {
192                 if((errno = (*(allocator->fn_finalize))(&block)))
193                         return errno;
194                         
195                 memset(block, 0, allocator->type_size);
196                 node->is_allocated = 0;
197         }
198         
199         /* get the node address. */
200         node = (allocator_node_t)(((byte*)block) - sizeof(s_allocator_node_t)); 
201         
202         /* the node becomes the free node and the free node become the next free node.*/
203         node->next = allocator->free;
204         allocator->free = node;
205         allocator->size--;
206         
207         return 0;
208 }
209
210 int
211 allocator_get_size(allocator_t allocator)
212 {
213         if(!allocator)
214     {
215         errno = EINVAL;
216         return -1;
217     }
218     
219     return allocator->size;
220 }
221
222 int
223 allocator_get_capacity(allocator_t allocator)
224 {
225         if(!allocator)
226     {
227         errno = EINVAL;
228         return -1;
229     }
230     
231    return allocator->capacity;
232 }
233
234 int
235 allocator_get_type_size(allocator_t allocator)
236 {
237
238         if(NULL == allocator)
239     {
240         errno = EINVAL;
241         return -1;
242     }
243     
244    return allocator->type_size;
245 }
246
247 int
248 allocator_is_empty(allocator_t allocator)
249 {
250         if(NULL == allocator)
251     {
252         errno = EINVAL;
253         return 0;
254     }
255     
256     return !(allocator->size);
257 }
258
259
260 int
261 allocator_is_full(allocator_t allocator)
262 {
263         if(NULL == allocator)
264     {
265         errno = EINVAL;
266         return 0;
267     }
268     
269     return (allocator->size == allocator->capacity);
270 }
271
272 int
273 allocator_get_block_capacity(allocator_t allocator)
274 {
275                 
276         if(!allocator)
277     {
278         errno = EINVAL;
279         return -1;
280     }
281     
282    return allocator->block_capacity;
283 }
284
285 int
286 allocator_get_capacity_available(allocator_t allocator)
287 {
288         if(!allocator)
289     {
290         errno = EINVAL;
291         return -1;
292     }
293     
294         return (allocator->capacity - allocator->size);
295 }
296
297 int
298 allocator_clear(allocator_t allocator)
299 {
300         allocator_block_t cur;
301         allocator_node_t node;
302         
303         int block_capacity, node_size, type_size;
304         fn_finalize_t fn_finalize;
305         void* type;
306         register int pos;
307         
308         
309         if(!allocator)
310         return EINVAL;
311     
312     
313     if(allocator->fn_finalize)
314         {
315                 fn_finalize = allocator->fn_finalize;
316                 block_capacity = allocator->block_capacity;
317                 type_size = allocator->type_size;
318                 node_size = type_size + sizeof(s_allocator_node_t);
319                 
320                 cur = allocator->head;
321                  
322                 while(cur)
323                 {
324                         /* type points to the first node */
325                         node = (allocator_node_t)(((byte*)cur) + sizeof(s_allocator_block_t));
326                         
327                         if(node->is_allocated)
328                         {
329                         
330                                 type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
331                         
332                                 /* apply the fn_finalize function to the first type */
333                                 
334                                 if((errno = (*fn_finalize)(&type)))
335                                         return errno;
336                                 
337                                 memset(type, 0, type_size);
338                                 node->is_allocated = 0;
339                         }
340                         
341                         /*clear all the other types */
342                         for(pos = 1; pos < block_capacity; pos++)
343                         {
344                                 node = (allocator_node_t)(((byte*)node) + node_size);
345                                 
346                                 if(node->is_allocated)
347                                 {
348                                         type = (void*)(((byte*)node) +  sizeof(s_allocator_node_t));
349                                 
350                                         /* apply the fn_finalize function to the first type */
351                                         
352                                         if((errno = (*fn_finalize)(&type)))
353                                                 return errno;
354                                 
355                                         memset(type, 0, type_size);
356                                         node->is_allocated = 0;
357                                 }
358                         }
359                 }
360                 
361                 cur = cur->next;
362         }
363         
364     allocator->free = allocator->first;
365     allocator->size = 0;
366     
367     return 0;
368 }