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 _OPENCV_ALLOCATOR_H_ 00032 #define _OPENCV_ALLOCATOR_H_ 00033 00034 #include <stdlib.h> 00035 #include <stdio.h> 00036 00037 namespace cvflann 00038 { 00039 00047 template <typename T> 00048 T* allocate(size_t count = 1) 00049 { 00050 T* mem = (T*) ::malloc(sizeof(T)*count); 00051 return mem; 00052 } 00053 00054 00070 const size_t WORDSIZE=16; 00071 const size_t BLOCKSIZE=8192; 00072 00073 class CV_EXPORTS PooledAllocator 00074 { 00075 /* We maintain memory alignment to word boundaries by requiring that all 00076 allocations be in multiples of the machine wordsize. */ 00077 /* Size of machine word in bytes. Must be power of 2. */ 00078 /* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */ 00079 00080 00081 int remaining; /* Number of bytes left in current block of storage. */ 00082 void* base; /* Pointer to base of current block of storage. */ 00083 void* loc; /* Current location in block to next allocate memory. */ 00084 int blocksize; 00085 00086 00087 public: 00088 int usedMemory; 00089 int wastedMemory; 00090 00094 PooledAllocator(int blocksize = BLOCKSIZE) 00095 { 00096 this->blocksize = blocksize; 00097 remaining = 0; 00098 base = NULL; 00099 00100 usedMemory = 0; 00101 wastedMemory = 0; 00102 } 00103 00107 ~PooledAllocator() 00108 { 00109 void *prev; 00110 00111 while (base != NULL) { 00112 prev = *((void **) base); /* Get pointer to prev block. */ 00113 ::free(base); 00114 base = prev; 00115 } 00116 } 00117 00122 void* allocateBytes(int size) 00123 { 00124 int blocksize; 00125 00126 /* Round size up to a multiple of wordsize. The following expression 00127 only works for WORDSIZE that is a power of 2, by masking last bits of 00128 incremented size to zero. 00129 */ 00130 size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1); 00131 00132 /* Check whether a new block must be allocated. Note that the first word 00133 of a block is reserved for a pointer to the previous block. 00134 */ 00135 if (size > remaining) { 00136 00137 wastedMemory += remaining; 00138 00139 /* Allocate new storage. */ 00140 blocksize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ? 00141 size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE; 00142 00143 // use the standard C malloc to allocate memory 00144 void* m = ::malloc(blocksize); 00145 if (!m) { 00146 fprintf(stderr,"Failed to allocate memory.\n"); 00147 exit(1); 00148 } 00149 00150 /* Fill first word of new block with pointer to previous block. */ 00151 ((void **) m)[0] = base; 00152 base = m; 00153 00154 int shift = 0; 00155 //int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1); 00156 00157 remaining = blocksize - sizeof(void*) - shift; 00158 loc = ((char*)m + sizeof(void*) + shift); 00159 } 00160 void* rloc = loc; 00161 loc = (char*)loc + size; 00162 remaining -= size; 00163 00164 usedMemory += size; 00165 00166 return rloc; 00167 } 00168 00176 template <typename T> 00177 T* allocate(size_t count = 1) 00178 { 00179 T* mem = (T*) this->allocateBytes((int)(sizeof(T)*count)); 00180 return mem; 00181 } 00182 00183 }; 00184 00185 } // namespace cvflann 00186 00187 #endif //_OPENCV_ALLOCATOR_H_