Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 /* 00004 00005 Heap Layers: An Extensible Memory Allocation Infrastructure 00006 00007 Copyright (C) 2000-2005 by Emery Berger 00008 http://www.cs.umass.edu/~emery 00009 emery@cs.umass.edu 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 This program is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with this program; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 */ 00026 00032 #ifndef _SEGHEAP_H_ 00033 #define _SEGHEAP_H_ 00034 00059 #include <assert.h> 00060 #include "bitstring.h" 00061 00062 namespace HL { 00063 00064 template <int NumBins, 00065 int (*getSizeClass) (const size_t), 00066 size_t (*getClassMaxSize) (const int), 00067 class LittleHeap, 00068 class BigHeap> 00069 class SegHeap : public LittleHeap { 00070 private: 00071 00072 typedef int (*scFunction) (const size_t); 00073 typedef size_t (*csFunction) (const int); 00074 00075 public: 00076 00077 inline SegHeap (void) 00078 : memoryHeld (0), 00079 maxObjectSize (((csFunction) getClassMaxSize) (NumBins - 1)) 00080 { 00081 for (int i = 0; i < NUM_ULONGS; i++) { 00082 binmap[i] = 0; 00083 } 00084 } 00085 00086 inline ~SegHeap (void) {} 00087 00088 inline size_t getMemoryHeld (void) const { 00089 return memoryHeld; 00090 } 00091 00092 // new... 00093 size_t getSize (void * ptr) { 00094 return LittleHeap::getSize (ptr); 00095 } 00096 00097 inline void * malloc (const size_t sz) { 00098 void * ptr = NULL; 00099 if (sz > maxObjectSize) { 00100 goto GET_MEMORY; 00101 } 00102 00103 { 00104 const int sc = ((scFunction) getSizeClass)(sz); 00105 assert (sc >= 0); 00106 assert (sc < NumBins); 00107 int idx = sc; 00108 int block = idx2block (idx); 00109 unsigned long map = binmap[block]; 00110 unsigned long bit = idx2bit (idx); 00111 00112 for (;;) { 00113 if (bit > map || bit == 0) { 00114 do { 00115 if (++block >= NUM_ULONGS) { 00116 goto GET_MEMORY; 00117 // return bigheap.malloc (sz); 00118 } 00119 } while ( (map = binmap[block]) == 0); 00120 00121 idx = block << SHIFTS_PER_ULONG; 00122 bit = 1; 00123 } 00124 00125 while ((bit & map) == 0) { 00126 bit <<= 1; 00127 assert(bit != 0); 00128 idx++; 00129 } 00130 00131 assert (idx < NumBins); 00132 ptr = myLittleHeap[idx].malloc (sz); 00133 00134 if (ptr == NULL) { 00135 binmap[block] = map &= ~bit; // Write through 00136 idx++; 00137 bit <<= 1; 00138 } else { 00139 return ptr; 00140 } 00141 } 00142 } 00143 00144 GET_MEMORY: 00145 if (ptr == NULL) { 00146 // There was no free memory in any of the bins. 00147 // Get some memory. 00148 ptr = bigheap.malloc (sz); 00149 } 00150 00151 return ptr; 00152 } 00153 00154 00155 inline void free (void * ptr) { 00156 // printf ("Free: %x (%d bytes)\n", ptr, getSize(ptr)); 00157 const size_t objectSize = getSize(ptr); // was bigheap.getSize(ptr) 00158 if (objectSize > maxObjectSize) { 00159 // printf ("free up! (size class = %d)\n", objectSizeClass); 00160 bigheap.free (ptr); 00161 } else { 00162 int objectSizeClass = ((scFunction) getSizeClass) (objectSize); 00163 assert (objectSizeClass >= 0); 00164 assert (objectSizeClass < NumBins); 00165 // Put the freed object into the right sizeclass heap. 00166 assert (getClassMaxSize(objectSizeClass) >= objectSize); 00167 #if 1 00168 while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) { 00169 objectSizeClass--; 00170 } 00171 #endif 00172 assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize); 00173 if (objectSizeClass > 0) { 00174 assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1)); 00175 } 00176 00177 00178 myLittleHeap[objectSizeClass].free (ptr); 00179 mark_bin (objectSizeClass); 00180 memoryHeld += objectSize; 00181 } 00182 } 00183 00184 00185 void clear (void) { 00186 int i; 00187 for (i = 0; i < NumBins; i++) { 00188 myLittleHeap[i].clear(); 00189 } 00190 for (int j = 0; j < NUM_ULONGS; j++) { 00191 binmap[j] = 0; 00192 } 00193 // bitstring.clear(); 00194 bigheap.clear(); 00195 memoryHeld = 0; 00196 } 00197 00198 private: 00199 00200 enum { BITS_PER_ULONG = 32 }; 00201 enum { SHIFTS_PER_ULONG = 5 }; 00202 enum { MAX_BITS = (NumBins + BITS_PER_ULONG - 1) & ~(BITS_PER_ULONG - 1) }; 00203 00204 00205 private: 00206 00207 static inline int idx2block (int i) { 00208 int blk = i >> SHIFTS_PER_ULONG; 00209 assert (blk < NUM_ULONGS); 00210 assert (blk >= 0); 00211 return blk; 00212 } 00213 00214 static inline unsigned long idx2bit (int i) { 00215 unsigned long bit = ((1U << ((i) & ((1U << SHIFTS_PER_ULONG)-1)))); 00216 return bit; 00217 } 00218 00219 00220 protected: 00221 00222 BigHeap bigheap; 00223 00224 enum { NUM_ULONGS = MAX_BITS / BITS_PER_ULONG }; 00225 unsigned long binmap[NUM_ULONGS]; 00226 00227 inline int get_binmap (int i) const { 00228 return binmap[i >> SHIFTS_PER_ULONG] & idx2bit(i); 00229 } 00230 00231 inline void mark_bin (int i) { 00232 binmap[i >> SHIFTS_PER_ULONG] |= idx2bit(i); 00233 } 00234 00235 inline void unmark_bin (int i) { 00236 binmap[i >> SHIFTS_PER_ULONG] &= ~(idx2bit(i)); 00237 } 00238 00239 size_t memoryHeld; 00240 00241 const size_t maxObjectSize; 00242 00243 // The little heaps. 00244 LittleHeap myLittleHeap[NumBins]; 00245 00246 }; 00247 00248 }; 00249 00250 00269 namespace HL { 00270 00271 template <int NumBins, 00272 int (*getSizeClass) (const size_t), 00273 size_t (*getClassMaxSize) (const int), 00274 class LittleHeap, 00275 class BigHeap> 00276 class StrictSegHeap : 00277 public SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap> 00278 { 00279 private: 00280 00281 typedef SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap> super; 00282 00283 typedef int (*scFunction) (const size_t); 00284 typedef size_t (*csFunction) (const int); 00285 00286 public: 00287 00288 void freeAll (void) { 00289 int i; 00290 for (i = 0; i < NumBins; i++) { 00291 const size_t sz = ((csFunction) getClassMaxSize)(i); 00292 void * ptr; 00293 while ((ptr = super::myLittleHeap[i].malloc (sz)) != NULL) { 00294 super::bigheap.free (ptr); 00295 } 00296 } 00297 for (int j = 0; j < super::NUM_ULONGS; j++) { 00298 super::binmap[j] = 0; 00299 } 00300 super::memoryHeld = 0; 00301 } 00302 00303 00309 inline void * malloc (const size_t sz) { 00310 void * ptr = NULL; 00311 if (sz <= super::maxObjectSize) { 00312 const int sizeClass = ((scFunction) getSizeClass) (sz); 00313 assert (sizeClass >= 0); 00314 assert (sizeClass < NumBins); 00315 ptr = super::myLittleHeap[sizeClass].malloc (sz); 00316 } 00317 if (!ptr) { 00318 ptr = super::bigheap.malloc (sz); 00319 } 00320 return ptr; 00321 } 00322 00323 inline void free (void * ptr) { 00324 const size_t objectSize = super::getSize(ptr); 00325 if (objectSize > super::maxObjectSize) { 00326 super::bigheap.free (ptr); 00327 } else { 00328 int objectSizeClass = ((scFunction) getSizeClass) (objectSize); 00329 assert (objectSizeClass >= 0); 00330 assert (objectSizeClass < NumBins); 00331 // Put the freed object into the right sizeclass heap. 00332 assert (getClassMaxSize(objectSizeClass) >= objectSize); 00333 while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) { 00334 objectSizeClass--; 00335 } 00336 assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize); 00337 if (objectSizeClass > 0) { 00338 assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1)); 00339 } 00340 00341 super::myLittleHeap[objectSizeClass].free (ptr); 00342 super::memoryHeld += objectSize; 00343 } 00344 } 00345 00346 }; 00347 00348 }; 00349 00350 00351 #endif