Eneboo - Documentación para desarrolladores
src/hoard/src/emptyclass.h
Ir a la documentación de este archivo.
00001 // -*- C++ -*-
00002 
00003 #ifndef _EMPTYCLASS_H_
00004 #define _EMPTYCLASS_H_
00005 
00006 #include "check.h"
00007 #include "array.h"
00008 #include "hldefines.h"
00009 
00015 namespace Hoard {
00016 
00017 template <class SuperblockType_,
00018           int EmptinessClasses>
00019 class EmptyClass {
00020 
00021   enum { SuperblockSize = sizeof(SuperblockType_) };
00022 
00023 public:
00024 
00025   typedef SuperblockType_ SuperblockType;
00026 
00027   EmptyClass (void)
00028   {
00029     for (int i = 0; i <= EmptinessClasses + 1; i++) {
00030       _available(i) = 0;
00031     }
00032   }
00033 
00034   void dumpStats (void) {
00035     for (int i = 0; i <= EmptinessClasses + 1; i++) {
00036       SuperblockType * s = _available(i);
00037       if (s) {
00038         //      fprintf (stderr, "EmptyClass: emptiness class = %d\n", i);
00039         while (s) {
00040           s->dumpStats();
00041           s = s->getNext();
00042         }
00043       }
00044     }
00045   }
00046 
00047 
00048   SuperblockType * getEmpty (void) {
00049     Check<EmptyClass, MyChecker> check (this);
00050     SuperblockType * s = _available(0);
00051     if (s && 
00052         (s->getObjectsFree() == s->getTotalObjects())) {
00053       // Got an empty one. Remove it.
00054       _available(0) = s->getNext();
00055       if (_available(0)) {
00056         _available(0)->setPrev (0);
00057       }
00058       s->setPrev (0);
00059       s->setNext (0);
00060       return s;
00061     }
00062     return 0;
00063   }
00064 
00065   SuperblockType * get (void) {
00066     Check<EmptyClass, MyChecker> check (this);
00067     // Return as empty a superblock as possible
00068     // by iterating from the emptiest to the fullest available class.
00069     for (int n = 0; n < EmptinessClasses + 1; n++) {
00070       SuperblockType * s = _available(n);
00071       while (s) {
00072         assert (s->isValidSuperblock());
00073         // Got one. Remove it.
00074         _available(n) = s->getNext();
00075         if (_available(n)) {
00076           _available(n)->setPrev (0);
00077         }
00078         s->setPrev (0);
00079         s->setNext (0);
00080 
00081 #ifndef NDEBUG
00082         // Verify that this superblock is *gone* from the lists.
00083         for (int z = 0; z < EmptinessClasses + 1; z++) {
00084           SuperblockType * p = _available(z);
00085           while (p) {
00086             assert (p != s);
00087             p = p->getNext();
00088           }
00089         }
00090 #endif
00091 
00092         // Ensure that we return a superblock that is as free as
00093         // possible.
00094         int cl = getFullness (s);
00095         if (cl > n) {
00096           put (s);
00097           SuperblockType * sNew = _available(n);
00098           assert (s != sNew);
00099           s = sNew;
00100         } else {
00101           return s;
00102         }
00103       }
00104     }
00105     return 0;
00106   }
00107 
00108   void put (SuperblockType * s) {
00109     Check<EmptyClass, MyChecker> check (this);
00110 
00111 #ifndef NDEBUG
00112     // Check to verify that this superblock is not already on one of the lists.
00113     for (int n = 0; n <= EmptinessClasses + 1; n++) {
00114       SuperblockType * p = _available(n);
00115       while (p) {
00116         assert (p != s);
00117         p = p->getNext();
00118       }
00119     }
00120 #endif
00121 
00122     // Put on the appropriate available list.
00123     int cl = getFullness (s);
00124 
00125     //    printf ("put %x, cl = %d\n", s, cl);
00126     s->setPrev (0);
00127     s->setNext (_available(cl));
00128     if (_available(cl)) {
00129       _available(cl)->setPrev (s);
00130     }
00131     _available(cl) = s;
00132   }
00133 
00134   INLINE MALLOC_FUNCTION void * malloc (size_t sz) {
00135     // Malloc from the fullest superblock first.
00136     for (int i = EmptinessClasses; i >= 0; i--) {
00137       SuperblockType * s = _available(i);
00138       // printf ("i\n");
00139       if (s) {
00140         int oldCl = getFullness (s);
00141         void * ptr = s->malloc (sz);
00142         int newCl = getFullness (s);
00143         if (ptr) {
00144           if (oldCl != newCl) {
00145             transfer (s, oldCl, newCl);
00146           }
00147           return ptr;
00148         }
00149       }
00150     }
00151     return NULL;
00152   }
00153 
00154   INLINE void free (void * ptr) {
00155     Check<EmptyClass, MyChecker> check (this);
00156     SuperblockType * s = getSuperblock (ptr);
00157     int oldCl = getFullness (s);
00158     s->free (ptr);
00159     int newCl = getFullness (s);
00160 
00161     if (oldCl != newCl) {
00162       // Transfer.
00163       transfer (s, oldCl, newCl);
00164     }
00165   }
00166 
00168   static INLINE SuperblockType * getSuperblock (void * ptr) {
00169     return SuperblockType::getSuperblock (ptr);
00170   }
00171 
00172 private:
00173 
00174   void transfer (SuperblockType * s, int oldCl, int newCl)
00175   {
00176     SuperblockType * prev = s->getPrev();
00177     SuperblockType * next = s->getNext();
00178     if (prev) { prev->setNext (next); }
00179     if (next) { next->setPrev (prev); }
00180     if (s == _available(oldCl)) {
00181       assert (prev == 0);
00182       _available(oldCl) = next;
00183     }
00184     s->setNext (_available(newCl));
00185     s->setPrev (0);
00186     if (_available(newCl)) { _available(newCl)->setPrev (s); }
00187     _available(newCl) = s;
00188   }
00189 
00190   static INLINE int getFullness (SuperblockType * s) {
00191     // Completely full = EmptinessClasses + 1
00192     // Completely empty (all available) = 0
00193     int total = s->getTotalObjects();
00194     int free = s->getObjectsFree();
00195     if (total == free) {
00196       return 0;
00197     } else {
00198       return 1 + (EmptinessClasses * (total - free)) / total;
00199     }
00200   }
00201 
00204   class MyChecker;
00205   friend class MyChecker;
00206 
00208   class MyChecker {
00209   public:
00210 #ifndef NDEBUG
00211     static void precondition (EmptyClass * e) {
00212       e->sanityCheckPre();
00213     }
00214     static void postcondition (EmptyClass * e) {
00215       e->sanityCheck();
00216     }
00217 #else
00218     static void precondition (EmptyClass *) {}
00219     static void postcondition (EmptyClass *) {}
00220 #endif
00221   };
00222 
00223   void sanityCheckPre (void) { sanityCheck(); }
00224 
00225   void sanityCheck (void) {
00226     for (int i = 0; i <= EmptinessClasses + 1; i++) {
00227       SuperblockType * s = _available(i);
00228       while (s) {
00229         assert (getFullness(s) == i);
00230         s = s->getNext();
00231       }
00232     }
00233   }
00234 
00237   Array<EmptinessClasses + 2, SuperblockType *> _available;
00238 
00239 };
00240 
00241 }
00242 
00243 
00244 #endif
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'