Eneboo - Documentación para desarrolladores
|
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