Blender V2.61 - r43446
|
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 }