Blender V2.61 - r43446

btGenericPoolAllocator.cpp

Go to the documentation of this file.
00001 
00006 /*
00007 Bullet Continuous Collision Detection and Physics Library
00008 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00009 
00010 This software is provided 'as-is', without any express or implied warranty.
00011 In no event will the authors be held liable for any damages arising from the use of this software.
00012 Permission is granted to anyone to use this software for any purpose,
00013 including commercial applications, and to alter it and redistribute it freely,
00014 subject to the following restrictions:
00015 
00016 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00017 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00018 3. This notice may not be removed or altered from any source distribution.
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     // find an avaliable free node with the correct size
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; // not found
00043 
00044 
00045     revindex = ptr;
00046     ptr = m_free_nodes[revindex];
00047     // post: ptr contains the node index, and revindex the index in m_free_nodes
00048 
00049     size_t  finalsize = m_allocated_sizes[ptr];
00050     finalsize -= num_elements;
00051 
00052     m_allocated_sizes[ptr] = num_elements;
00053 
00054     // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
00055 
00056     if(finalsize>0) // preserve free node, there are some free memory
00057     {
00058         m_free_nodes[revindex] = ptr + num_elements;
00059         m_allocated_sizes[ptr + num_elements] = finalsize;
00060     }
00061     else // delete free node
00062     {
00063         // swap with end
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     // a free node is found
00128     if(alloc_pos != BT_UINT_MAX)
00129     {
00130         return get_element_data(alloc_pos);
00131     }
00132     // allocate directly on pool
00133     alloc_pos = allocate_from_pool(element_count);
00134 
00135     if(alloc_pos == BT_UINT_MAX) return NULL; // not space
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     // calc offset
00144     if(pointer_pos<pool_pos) return false;//other pool
00145     size_t offset = size_t(pointer_pos - pool_pos);
00146     if(offset>=get_pool_capacity()) return false;// far away
00147 
00148     // find free position
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     // destroy pools
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 // creates a pool
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) // failback
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 // main allocator
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 // global allocator
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 }