00001
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) = NULL;
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
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
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
00068
00069 for (int n = 0; n < EmptinessClasses + 1; n++) {
00070 SuperblockType * s = _available(n);
00071 while (s) {
00072 assert (s->isValidSuperblock());
00073
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
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
00093
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
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
00123 int cl = getFullness (s);
00124
00125
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
00136 for (int i = EmptinessClasses; i >= 0; i--) {
00137 SuperblockType * s = _available(i);
00138
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
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
00192
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