Eneboo - Documentación para desarrolladores
src/hoard/src/hoardmanager.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-2007 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 
00027 #ifndef _HOARDMANAGER_H_
00028 #define _HOARDMANAGER_H_
00029 
00030 #include <cstdlib>
00031 #include <new>
00032 
00033 // Hoard-specific Heap Layers
00034 #include "sassert.h"
00035 #include "statistics.h"
00036 #include "emptyclass.h"
00037 #include "array.h"
00038 #include "manageonesuperblock.h"
00039 
00040 
00041 // Generic Heap Layers
00042 #include "bins.h"
00043 #include "basehoardmanager.h"
00044 #include "emptyhoardmanager.h"
00045 #include "guard.h"
00046 #include "hldefines.h"
00047 
00048 using namespace HL;
00049 
00058 namespace Hoard {
00059 
00060 template <class SourceHeap,
00061           class ParentHeap,
00062           class SuperblockType_,
00063           int EmptinessClasses,
00064           class LockType,
00065           class thresholdFunctionClass,
00066           class HeapType>
00067 class HoardManager : public BaseHoardManager<SuperblockType_>,
00068                      public thresholdFunctionClass
00069 {
00070 public:
00071 
00072   HoardManager (void)
00073     : _magic (MAGIC_NUMBER)
00074   {}
00075 
00076   virtual ~HoardManager (void) {}
00077 
00078   typedef SuperblockType_ SuperblockType;
00079 
00081   enum { Alignment = sizeof(double) };
00082 
00083 
00084   MALLOC_FUNCTION INLINE void * malloc (size_t sz)
00085   {
00086     Check<HoardManager, sanityCheck> check (this);
00087     const int binIndex = binType::getSizeClass(sz);
00088     size_t realSize = binType::getClassSize (binIndex);
00089     assert (realSize >= sz);
00090 
00091     // Iterate until we succeed in allocating memory.
00092     void * ptr = getObject (binIndex, realSize);
00093     if (ptr) {
00094       return ptr;
00095     } else {
00096       return slowPathMalloc (realSize);
00097     }
00098   }
00099 
00100 
00102   NO_INLINE void put (SuperblockType * s, size_t sz) {
00103     HL::Guard<LockType> l (_theLock);
00104 
00105     assert (s->getOwner() != this);
00106     Check<HoardManager, sanityCheck> check (this);
00107 
00108     const int binIndex = binType::getSizeClass(sz);
00109 
00110     // Check to see whether this superblock puts us over.
00111     Statistics& stats = _stats(binIndex);
00112     int a = stats.getAllocated() + s->getTotalObjects();
00113     int u = stats.getInUse() + (s->getTotalObjects() - s->getObjectsFree());
00114 
00115     if (thresholdFunctionClass::function (u, a, sz)) {
00116       // We've crossed the threshold function,
00117       // so we move this superblock up to the parent.
00118       _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(s), sz);
00119     } else {
00120       unlocked_put (s, sz);
00121     }
00122   }
00123 
00124 
00126   NO_INLINE SuperblockType * get (size_t sz, HeapType * dest) {
00127     HL::Guard<LockType> l (_theLock);
00128     Check<HoardManager, sanityCheck> check (this);
00129     const int binIndex = binType::getSizeClass (sz);
00130     SuperblockType * s = _otherBins(binIndex).get();
00131     if (s) {
00132       assert (s->isValidSuperblock());
00133       
00134       // Update the statistics, removing objects in use and allocated for s.
00135       decStatsSuperblock (s, binIndex);
00136       s->setOwner (dest);
00137     }
00138     // printf ("getting sb %x (size %d) on %x\n", (void *) s, sz, (void *) this);
00139     return s;
00140   }
00141 
00143   INLINE void free (void * ptr) {
00144     Check<HoardManager, sanityCheck> check (this);
00145 
00146     // Get the corresponding superblock.
00147     SuperblockType * s = SuperHeap::getSuperblock (ptr);
00148  
00149     assert (s->getOwner() == this);
00150 
00151     // Find out which bin it belongs to.
00152     // Note that we assume that all pointers have been correctly
00153     // normalized at this point.
00154     assert (s->normalize (ptr) == ptr);
00155 
00156     const size_t sz = s->getObjectSize ();
00157     const int binIndex = binType::getSizeClass (sz);
00158 
00159     // Free the object.
00160     _otherBins(binIndex).free (ptr);
00161 
00162 
00163     // Update statistics.
00164     Statistics& stats = _stats(binIndex);
00165     int u = stats.getInUse();
00166     const int a = stats.getAllocated();
00167     if (u > 0)
00168       u--;
00169     stats.setInUse (u);
00170 
00171     // Free up a superblock if we've crossed the emptiness threshold.
00172 
00173     if (thresholdFunctionClass::function (u, a, sz)) {
00174 
00175       slowPathFree (binIndex, u, a);
00176 
00177     }
00178   }
00179 
00180   INLINE void lock (void) {
00181     _theLock.lock();
00182   }
00183 
00184   INLINE void unlock (void) {
00185     _theLock.unlock();
00186   }
00187 
00188 private:
00189 
00190   typedef BaseHoardManager<SuperblockType_> SuperHeap;
00191 
00192   enum { SuperblockSize = sizeof(SuperblockType_) };
00193 
00195   HL::sassert<((SuperblockSize & (SuperblockSize-1)) == 0)> verifyPowerOfTwo;
00196 
00197   enum { MAGIC_NUMBER = 0xfeeddadd };
00198 
00200   const unsigned long _magic;
00201 
00202   inline int isValid (void) const {
00203     return (_magic == MAGIC_NUMBER);
00204   }
00205 
00206   sassert<sizeof(typename SuperblockType::Header) % sizeof(double) == 0>
00207     verifyHeaderRightSize;
00208 
00209 
00211   typedef HL::bins<typename SuperblockType::Header, SuperblockSize> binType;
00212 
00214   enum { NumBins = binType::NUM_BINS };
00215 
00216   NO_INLINE void slowPathFree (int binIndex, int u, int a) {
00217     // We've crossed the threshold.
00218     // Remove a superblock and give it to the 'parent heap.'
00219     Check<HoardManager, sanityCheck> check (this);
00220     
00221     //  printf ("HoardManager: this = %x, getting a superblock\n", this);
00222     
00223     SuperblockType * sb = _otherBins(binIndex).get ();
00224     
00225     // We should always get one.
00226     assert (sb);
00227     if (sb) {
00228 
00229       const size_t sz = binType::getClassSize (binIndex);
00230       Statistics& stats = _stats(binIndex);
00231       int totalObjects = sb->getTotalObjects();
00232       stats.setInUse (u - (totalObjects - sb->getObjectsFree()));
00233       stats.setAllocated (a - totalObjects);
00234 
00235       // Give it to the parent heap.
00238       _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(sb), sz);
00239       assert (sb->isValidSuperblock());
00240 
00241     }
00242   }
00243 
00244 
00245   NO_INLINE void unlocked_put (SuperblockType * s, size_t sz) {
00246     if (!s || !s->isValidSuperblock()) {
00247       return;
00248     }
00249 
00250     Check<HoardManager, sanityCheck> check (this);
00251 
00252     const int binIndex = binType::getSizeClass(sz);
00253 
00254     // Now put it on this heap.
00255     s->setOwner (reinterpret_cast<HeapType *>(this));
00256     _otherBins(binIndex).put (s);
00257 
00258     // Update the heap statistics with the allocated and in use stats
00259     // for the superblock.
00260 
00261     addStatsSuperblock (s, binIndex);
00262     assert (s->isValidSuperblock());
00263 
00264   }
00265 
00266   void addStatsSuperblock (SuperblockType * s, int binIndex) {
00267     Statistics& stats = _stats(binIndex);
00268     
00269     int a = stats.getAllocated();
00270     int u = stats.getInUse();
00271     int totalObjects = s->getTotalObjects();
00272     stats.setInUse (u + (totalObjects - s->getObjectsFree()));
00273     stats.setAllocated (a + totalObjects);
00274   }
00275 
00276 
00277   void decStatsSuperblock (SuperblockType * s, int binIndex) {
00278     Statistics& stats = _stats(binIndex);
00279     
00280     int a = stats.getAllocated();
00281     int u = stats.getInUse();
00282     int totalObjects = s->getTotalObjects();
00283     stats.setInUse (u - (totalObjects - s->getObjectsFree()));
00284     stats.setAllocated (a - totalObjects);
00285   }
00286 
00287   MALLOC_FUNCTION NO_INLINE void * slowPathMalloc (size_t sz) {
00288     const int binIndex = binType::getSizeClass (sz);
00289     size_t realSize = binType::getClassSize (binIndex);
00290     assert (realSize >= sz);
00291     for (;;) {
00292       Check<HoardManager, sanityCheck> check (this);
00293       void * ptr = getObject (binIndex, realSize);
00294       if (ptr) {
00295         return ptr;
00296       } else {
00297         Check<HoardManager, sanityCheck> check (this);
00298         // Return null if we can't allocate another superblock.
00299         if (!getAnotherSuperblock (realSize)) {
00300           //      fprintf (stderr, "HoardManager::malloc - no memory.\n");
00301           return 0;
00302         }
00303       }
00304     }
00305   }
00306 
00308   MALLOC_FUNCTION INLINE void * getObject (int binIndex, size_t sz) {
00309     Check<HoardManager, sanityCheck> check (this);
00310     void * ptr = _otherBins(binIndex).malloc (sz);
00311     if (ptr) {
00312       // We got one. Update stats.
00313       int u = _stats(binIndex).getInUse();
00314       _stats(binIndex).setInUse (u+1);
00315     }
00316     return ptr;
00317   }
00318 
00319   friend class sanityCheck;
00320 
00321   class sanityCheck {
00322   public:
00323     inline static void precondition (HoardManager * h) {
00324       checkInvariant(h);
00325     }
00326     inline static void postcondition (HoardManager * h) {
00327       checkInvariant(h);
00328     }
00329   private:
00330     inline static void checkInvariant (HoardManager * h) {
00331       assert (h->isValid());
00332     }
00333   };
00334 
00335 public:
00336 
00337   NO_INLINE void * getAnotherSuperblock (size_t sz) {
00338 
00339     // NB: This function should be on the slow path.
00340 
00341     SuperblockType * sb = NULL;
00342 
00343     // Try the parent heap.
00344     // NOTE: We change the superblock type here!
00345     sb = reinterpret_cast<SuperblockType *>(_ph.get (sz, reinterpret_cast<ParentHeap *>(this)));
00346 
00347     if (sb) {
00348       if (!sb->isValidSuperblock()) {
00349         // As above - drop any invalid superblocks.
00350         sb = NULL;
00351       }
00352 
00353     } else {
00354       // Nothing - get memory from the source.
00355       void * ptr = _sourceHeap.malloc (SuperblockSize);
00356       if (!ptr) {
00357         return 0;
00358       }
00359       sb = new (ptr) SuperblockType (sz);
00360     }
00361 
00362     // Put the superblock into its appropriate bin.
00363     if (sb) {
00364       unlocked_put (sb, sz);
00365     }
00366     return sb;
00367   }
00368 
00369 private:
00370 
00371   LockType _theLock;
00372 
00374   Array<NumBins, Statistics> _stats;
00375 
00376   typedef SuperblockType * SuperblockTypePointer;
00377 
00378   typedef EmptyClass<SuperblockType, EmptinessClasses> OrganizedByEmptiness;
00379 
00380   typedef ManageOneSuperblock<OrganizedByEmptiness> BinManager;
00381 
00383   Array<NumBins, BinManager> _otherBins;
00384 
00386   ParentHeap _ph;
00387 
00389   SourceHeap _sourceHeap;
00390 
00391 };
00392 
00393 }
00394 
00395 #endif
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'