Go to the documentation of this file.00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "btGenericPoolAllocator.h"
00022
00023
00024
00026
00027 size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
00028 {
00029 size_t ptr = BT_UINT_MAX;
00030
00031 if(m_free_nodes_count == 0) return BT_UINT_MAX;
00032
00033 size_t revindex = m_free_nodes_count;
00034
00035 while(revindex-- && ptr == BT_UINT_MAX)
00036 {
00037 if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
00038 {
00039 ptr = revindex;
00040 }
00041 }
00042 if(ptr == BT_UINT_MAX) return BT_UINT_MAX;
00043
00044
00045 revindex = ptr;
00046 ptr = m_free_nodes[revindex];
00047
00048
00049 size_t finalsize = m_allocated_sizes[ptr];
00050 finalsize -= num_elements;
00051
00052 m_allocated_sizes[ptr] = num_elements;
00053
00054
00055
00056 if(finalsize>0)
00057 {
00058 m_free_nodes[revindex] = ptr + num_elements;
00059 m_allocated_sizes[ptr + num_elements] = finalsize;
00060 }
00061 else
00062 {
00063
00064 m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
00065 m_free_nodes_count--;
00066 }
00067
00068 return ptr;
00069 }
00070
00071 size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
00072 {
00073 if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
00074
00075 size_t ptr = m_allocated_count;
00076
00077 m_allocated_sizes[m_allocated_count] = num_elements;
00078 m_allocated_count+=num_elements;
00079
00080 return ptr;
00081 }
00082
00083
00084 void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
00085 {
00086 m_allocated_count = 0;
00087 m_free_nodes_count = 0;
00088
00089 m_element_size = element_size;
00090 m_max_element_count = element_count;
00091
00092
00093
00094
00095 m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
00096 m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
00097 m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
00098
00099 for (size_t i = 0;i< m_max_element_count;i++ )
00100 {
00101 m_allocated_sizes[i] = 0;
00102 }
00103 }
00104
00105 void btGenericMemoryPool::end_pool()
00106 {
00107 btAlignedFree(m_pool);
00108 btAlignedFree(m_free_nodes);
00109 btAlignedFree(m_allocated_sizes);
00110 m_allocated_count = 0;
00111 m_free_nodes_count = 0;
00112 }
00113
00114
00116
00119 void * btGenericMemoryPool::allocate(size_t size_bytes)
00120 {
00121
00122 size_t module = size_bytes%m_element_size;
00123 size_t element_count = size_bytes/m_element_size;
00124 if(module>0) element_count++;
00125
00126 size_t alloc_pos = allocate_from_free_nodes(element_count);
00127
00128 if(alloc_pos != BT_UINT_MAX)
00129 {
00130 return get_element_data(alloc_pos);
00131 }
00132
00133 alloc_pos = allocate_from_pool(element_count);
00134
00135 if(alloc_pos == BT_UINT_MAX) return NULL;
00136 return get_element_data(alloc_pos);
00137 }
00138
00139 bool btGenericMemoryPool::freeMemory(void * pointer)
00140 {
00141 unsigned char * pointer_pos = (unsigned char *)pointer;
00142 unsigned char * pool_pos = (unsigned char *)m_pool;
00143
00144 if(pointer_pos<pool_pos) return false;
00145 size_t offset = size_t(pointer_pos - pool_pos);
00146 if(offset>=get_pool_capacity()) return false;
00147
00148
00149 m_free_nodes[m_free_nodes_count] = offset/m_element_size;
00150 m_free_nodes_count++;
00151 return true;
00152 }
00153
00154
00156
00157
00158 btGenericPoolAllocator::~btGenericPoolAllocator()
00159 {
00160
00161 size_t i;
00162 for (i=0;i<m_pool_count;i++)
00163 {
00164 m_pools[i]->end_pool();
00165 btAlignedFree(m_pools[i]);
00166 }
00167 }
00168
00169
00170
00171 btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
00172 {
00173 if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
00174
00175 btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
00176
00177 m_pools[m_pool_count] = newptr;
00178
00179 m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
00180
00181 m_pool_count++;
00182 return newptr;
00183 }
00184
00185 void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
00186 {
00187
00188 btGenericMemoryPool * pool = NULL;
00189
00190
00191 if(size_bytes<=get_pool_capacity())
00192 {
00193 pool = push_new_pool();
00194 }
00195
00196 if(pool==NULL)
00197 {
00198 return btAlignedAlloc(size_bytes,16);
00199 }
00200
00201 return pool->allocate(size_bytes);
00202 }
00203
00204 bool btGenericPoolAllocator::failback_free(void * pointer)
00205 {
00206 btAlignedFree(pointer);
00207 return true;
00208 }
00209
00210
00212
00215 void * btGenericPoolAllocator::allocate(size_t size_bytes)
00216 {
00217 void * ptr = NULL;
00218
00219 size_t i = 0;
00220 while(i<m_pool_count && ptr == NULL)
00221 {
00222 ptr = m_pools[i]->allocate(size_bytes);
00223 ++i;
00224 }
00225
00226 if(ptr) return ptr;
00227
00228 return failback_alloc(size_bytes);
00229 }
00230
00231 bool btGenericPoolAllocator::freeMemory(void * pointer)
00232 {
00233 bool result = false;
00234
00235 size_t i = 0;
00236 while(i<m_pool_count && result == false)
00237 {
00238 result = m_pools[i]->freeMemory(pointer);
00239 ++i;
00240 }
00241
00242 if(result) return true;
00243
00244 return failback_free(pointer);
00245 }
00246
00248
00249
00250 #define BT_DEFAULT_POOL_SIZE 32768
00251 #define BT_DEFAULT_POOL_ELEMENT_SIZE 8
00252
00253
00254 class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator
00255 {
00256 public:
00257 GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
00258 {
00259 }
00260 };
00261
00262
00263 GIM_STANDARD_ALLOCATOR g_main_allocator;
00264
00265
00266 void * btPoolAlloc(size_t size)
00267 {
00268 return g_main_allocator.allocate(size);
00269 }
00270
00271 void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
00272 {
00273 void * newptr = btPoolAlloc(newsize);
00274 size_t copysize = oldsize<newsize?oldsize:newsize;
00275 memcpy(newptr,ptr,copysize);
00276 btPoolFree(ptr);
00277 return newptr;
00278 }
00279
00280 void btPoolFree(void *ptr)
00281 {
00282 g_main_allocator.freeMemory(ptr);
00283 }