1 #include "goomsl_heap.h"
2 #include <stdlib.h>
3 
4 struct _GOOM_HEAP {
5   void **arrays;
6   int number_of_arrays;
7   int size_of_each_array;
8   int consumed_in_last_array;
9 };
10 
11 /* Constructors / Destructor */
goom_heap_new(void)12 GoomHeap *goom_heap_new(void)
13 {
14   return goom_heap_new_with_granularity(4096);
15 }
16 
goom_heap_new_with_granularity(int granularity)17 GoomHeap *goom_heap_new_with_granularity(int granularity)
18 {
19   GoomHeap *_this;
20   _this = (GoomHeap*)malloc(sizeof(GoomHeap));
21   _this->number_of_arrays   = 0;
22   _this->size_of_each_array = granularity;
23   _this->consumed_in_last_array = 0;
24   _this->arrays = (void**)malloc(sizeof(void*));
25   return _this;
26 }
27 
goom_heap_delete(GoomHeap * _this)28 void goom_heap_delete(GoomHeap *_this)
29 {
30   int i;
31   for (i=0;i<_this->number_of_arrays;++i) {
32     free(_this->arrays[i]);
33   }
34   free(_this->arrays);
35   free(_this);
36 }
37 
align_it(GoomHeap * _this,int alignment)38 static void align_it(GoomHeap *_this, int alignment)
39 {
40   if ((alignment > 1) && (_this->number_of_arrays>0)) {
41     void *last_array = _this->arrays[_this->number_of_arrays - 1];
42     int   last_address = (int)last_array + _this->consumed_in_last_array;
43     int   decal = (last_address % alignment);
44     if (decal != 0) {
45       _this->consumed_in_last_array += alignment - decal;
46     }
47   }
48 }
49 
goom_heap_malloc_with_alignment_prefixed(GoomHeap * _this,int nb_bytes,int alignment,int prefix_bytes)50 void     *goom_heap_malloc_with_alignment_prefixed(GoomHeap *_this, int nb_bytes,
51                                                    int alignment, int prefix_bytes)
52 {
53   void *retval = NULL;
54 
55   /* d'abord on gere les problemes d'alignement */
56   _this->consumed_in_last_array += prefix_bytes;
57   align_it(_this, alignment);
58 
59   /* ensuite on verifie que la quantite de memoire demandee tient dans le buffer */
60   if ((_this->consumed_in_last_array + nb_bytes >= _this->size_of_each_array)
61       || (_this->number_of_arrays == 0)) {
62 
63     if (prefix_bytes + nb_bytes + alignment >= _this->size_of_each_array) {
64 
65       /* Si la zone demandee est plus grosse que la granularitee */
66       /* On alloue un buffer plus gros que les autres */
67       _this->arrays = (void**)realloc(_this->arrays, sizeof(void*) * (_this->number_of_arrays+2));
68 
69       _this->number_of_arrays += 1;
70       _this->consumed_in_last_array = prefix_bytes;
71 
72       _this->arrays[_this->number_of_arrays - 1] = malloc(prefix_bytes + nb_bytes + alignment);
73       align_it(_this,alignment);
74       retval = (void*)((char*)_this->arrays[_this->number_of_arrays - 1] + _this->consumed_in_last_array);
75 
76       /* puis on repart sur un nouveau buffer vide */
77       _this->number_of_arrays += 1;
78       _this->consumed_in_last_array = 0;
79       _this->arrays[_this->number_of_arrays - 1] = malloc(_this->size_of_each_array);
80       return retval;
81     }
82     else {
83       _this->number_of_arrays += 1;
84       _this->consumed_in_last_array = prefix_bytes;
85       _this->arrays = (void**)realloc(_this->arrays, sizeof(void*) * _this->number_of_arrays);
86 
87       _this->arrays[_this->number_of_arrays - 1] = malloc(_this->size_of_each_array);
88       align_it(_this,alignment);
89     }
90   }
91   retval = (void*)((char*)_this->arrays[_this->number_of_arrays - 1] + _this->consumed_in_last_array);
92   _this->consumed_in_last_array += nb_bytes;
93   return retval;
94 }
95 
goom_heap_malloc_with_alignment(GoomHeap * _this,int nb_bytes,int alignment)96 void *goom_heap_malloc_with_alignment(GoomHeap *_this, int nb_bytes, int alignment)
97 {
98   return goom_heap_malloc_with_alignment_prefixed(_this, nb_bytes, alignment, 0);
99 }
100 
goom_heap_malloc(GoomHeap * _this,int nb_bytes)101 void *goom_heap_malloc(GoomHeap *_this, int nb_bytes)
102 {
103   return goom_heap_malloc_with_alignment(_this,nb_bytes,1);
104 }
105 
106