Merge branch 'blender2.7'
[blender.git] / intern / dualcon / intern / MemoryAllocator.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Tao Ju
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #ifndef __MEMORYALLOCATOR_H__
24 #define __MEMORYALLOCATOR_H__
25
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #define HEAP_BASE 16
30 #define UCHAR unsigned char
31
32 /**
33  * Customized memory allocators that allocates/deallocates memory in chunks
34  *
35  * @author Tao Ju
36  */
37
38
39
40 /**
41  * Base class of memory allocators
42  */
43 class VirtualMemoryAllocator
44 {
45 public:
46 virtual ~VirtualMemoryAllocator() {}
47
48 virtual void *allocate( ) = 0;
49 virtual void deallocate(void *obj) = 0;
50 virtual void destroy( ) = 0;
51 virtual void printInfo( ) = 0;
52
53 virtual int getAllocated( ) = 0;
54 virtual int getAll( ) = 0;
55 virtual int getBytes( ) = 0;
56
57 #ifdef WITH_CXX_GUARDEDALLOC
58         MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:VirtualMemoryAllocator")
59 #endif
60
61 };
62
63 /**
64  * Dynamic memory allocator - allows allocation/deallocation
65  *
66  * Note: there are 4 bytes overhead for each allocated yet unused object.
67  */
68 template < int N >
69 class MemoryAllocator : public VirtualMemoryAllocator
70 {
71 private:
72
73 /// Constants
74 int HEAP_UNIT, HEAP_MASK;
75
76 /// Data array
77 UCHAR **data;
78
79 /// Allocation stack
80 UCHAR ***stack;
81
82 /// Number of data blocks
83 int datablocknum;
84
85 /// Number of stack blocks
86 int stackblocknum;
87
88 /// Size of stack
89 int stacksize;
90
91 /// Number of available objects on stack
92 int available;
93
94 /**
95  * Allocate a memory block
96  */
97 void allocateDataBlock( )
98 {
99         // Allocate a data block
100         datablocknum += 1;
101         data = ( UCHAR ** )realloc(data, sizeof (UCHAR *) * datablocknum);
102         data[datablocknum - 1] = ( UCHAR * )malloc(HEAP_UNIT * N);
103
104         // Update allocation stack
105         for (int i = 0; i < HEAP_UNIT; i++)
106         {
107                 stack[0][i] = (data[datablocknum - 1] + i * N);
108         }
109         available = HEAP_UNIT;
110 }
111
112 /**
113  * Allocate a stack block, to store more deallocated objects
114  */
115 void allocateStackBlock( )
116 {
117         // Allocate a stack block
118         stackblocknum += 1;
119         stacksize += HEAP_UNIT;
120         stack = ( UCHAR *** )realloc(stack, sizeof (UCHAR * *) * stackblocknum);
121         stack[stackblocknum - 1] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) );
122 }
123
124
125 public:
126 /**
127  * Constructor
128  */
129 MemoryAllocator( )
130 {
131         HEAP_UNIT = 1 << HEAP_BASE;
132         HEAP_MASK = (1 << HEAP_BASE) - 1;
133
134         data = ( UCHAR ** )malloc(sizeof(UCHAR *) );
135         data[0] = ( UCHAR * )malloc(HEAP_UNIT * N);
136         datablocknum = 1;
137
138         stack = ( UCHAR *** )malloc(sizeof (UCHAR * *) );
139         stack[0] = ( UCHAR ** )malloc(HEAP_UNIT * sizeof (UCHAR *) );
140         stackblocknum = 1;
141         stacksize = HEAP_UNIT;
142         available = HEAP_UNIT;
143
144         for (int i = 0; i < HEAP_UNIT; i++)
145         {
146                 stack[0][i] = (data[0] + i * N);
147         }
148 }
149
150 /**
151  * Destructor
152  */
153 void destroy( )
154 {
155         int i;
156         for (i = 0; i < datablocknum; i++)
157         {
158                 free(data[i]);
159         }
160         for (i = 0; i < stackblocknum; i++)
161         {
162                 free(stack[i]);
163         }
164         free(data);
165         free(stack);
166 }
167
168 /**
169  * Allocation method
170  */
171 void *allocate( )
172 {
173         if (available == 0)
174         {
175                 allocateDataBlock( );
176         }
177
178         // printf("Allocating %d\n", header[ allocated ]) ;
179         available--;
180         return (void *)stack[available >> HEAP_BASE][available & HEAP_MASK];
181 }
182
183 /**
184  * De-allocation method
185  */
186 void deallocate(void *obj)
187 {
188         if (available == stacksize)
189         {
190                 allocateStackBlock( );
191         }
192
193         // printf("De-allocating %d\n", ( obj - data ) / N ) ;
194         stack[available >> HEAP_BASE][available & HEAP_MASK] = (UCHAR *)obj;
195         available++;
196         // printf("%d %d\n", allocated, header[ allocated ]) ;
197 }
198
199 /**
200  * Print information
201  */
202 void printInfo( )
203 {
204         printf("Bytes: %d Used: %d Allocated: %d Maxfree: %d\n", getBytes(), getAllocated(), getAll(), stacksize);
205 }
206
207 /**
208  * Query methods
209  */
210 int getAllocated( )
211 {
212         return HEAP_UNIT * datablocknum - available;
213 };
214
215 int getAll( )
216 {
217         return HEAP_UNIT * datablocknum;
218 };
219
220 int getBytes( )
221 {
222         return N;
223 };
224
225 #ifdef WITH_CXX_GUARDEDALLOC
226         MEM_CXX_CLASS_ALLOC_FUNCS("DUALCON:MemoryAllocator")
227 #endif
228
229 };
230
231 #endif  /* __MEMORYALLOCATOR_H__ */