00001 /*********************************************************************** 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. 00005 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. 00006 * 00007 * THE BSD LICENSE 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00020 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00021 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00022 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00023 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00024 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00028 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 *************************************************************************/ 00030 00031 #ifndef RTABMAP_FLANN_ALLOCATOR_H_ 00032 #define RTABMAP_FLANN_ALLOCATOR_H_ 00033 00034 #include <stdlib.h> 00035 #include <stdio.h> 00036 00037 00038 namespace rtflann 00039 { 00040 00048 template <typename T> 00049 T* allocate(size_t count = 1) 00050 { 00051 T* mem = (T*) ::malloc(sizeof(T)*count); 00052 return mem; 00053 } 00054 00055 00056 00072 const size_t WORDSIZE=16; 00073 const size_t BLOCKSIZE=8192; 00074 00075 class PooledAllocator 00076 { 00077 /* We maintain memory alignment to word boundaries by requiring that all 00078 allocations be in multiples of the machine wordsize. */ 00079 /* Size of machine word in bytes. Must be power of 2. */ 00080 /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ 00081 00082 00083 int remaining; /* Number of bytes left in current block of storage. */ 00084 void* base; /* Pointer to base of current block of storage. */ 00085 void* loc; /* Current location in block to next allocate memory. */ 00086 int blocksize; 00087 00088 00089 public: 00090 int usedMemory; 00091 int wastedMemory; 00092 00096 PooledAllocator(int blocksize = BLOCKSIZE) 00097 { 00098 this->blocksize = blocksize; 00099 remaining = 0; 00100 base = NULL; 00101 00102 usedMemory = 0; 00103 wastedMemory = 0; 00104 } 00105 00109 ~PooledAllocator() 00110 { 00111 free(); 00112 } 00113 00114 void free() 00115 { 00116 void* prev; 00117 while (base != NULL) { 00118 prev = *((void**) base); /* Get pointer to prev block. */ 00119 ::free(base); 00120 base = prev; 00121 } 00122 base = NULL; 00123 remaining = 0; 00124 usedMemory = 0; 00125 wastedMemory = 0; 00126 } 00127 00132 void* allocateMemory(int size) 00133 { 00134 int blocksize; 00135 00136 /* Round size up to a multiple of wordsize. The following expression 00137 only works for WORDSIZE that is a power of 2, by masking last bits of 00138 incremented size to zero. 00139 */ 00140 size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); 00141 00142 /* Check whether a new block must be allocated. Note that the first word 00143 of a block is reserved for a pointer to the previous block. 00144 */ 00145 if (size > remaining) { 00146 00147 wastedMemory += remaining; 00148 00149 /* Allocate new storage. */ 00150 blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? 00151 size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; 00152 00153 // use the standard C malloc to allocate memory 00154 void* m = ::malloc(blocksize); 00155 if (!m) { 00156 fprintf(stderr,"Failed to allocate memory.\n"); 00157 return NULL; 00158 } 00159 00160 /* Fill first word of new block with pointer to previous block. */ 00161 ((void**) m)[0] = base; 00162 base = m; 00163 00164 int shift = 0; 00165 //int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); 00166 00167 remaining = blocksize - sizeof(void*) - shift; 00168 loc = ((char*)m + sizeof(void*) + shift); 00169 } 00170 void* rloc = loc; 00171 loc = (char*)loc + size; 00172 remaining -= size; 00173 00174 usedMemory += size; 00175 00176 return rloc; 00177 } 00178 00186 template <typename T> 00187 T* allocate(size_t count = 1) 00188 { 00189 T* mem = (T*) this->allocateMemory((int)(sizeof(T)*count)); 00190 return mem; 00191 } 00192 00193 }; 00194 00195 } 00196 00197 inline void* operator new (std::size_t size, rtflann::PooledAllocator& allocator) 00198 { 00199 return allocator.allocateMemory(size) ; 00200 } 00201 00202 #endif //FLANN_ALLOCATOR_H_