Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/segheap.h
Ir a la documentación de este archivo.
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
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'