00001
00002
00003 #ifndef _LOOSESLOTHEAP_H_
00004 #define _LOOSESLOTHEAP_H_
00005
00006 #include <assert.h>
00007
00008 #include "bigchunk.h"
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00030 class LooseSlotHeap {
00031 public:
00032
00033 inline LooseSlotHeap (void);
00034 inline ~LooseSlotHeap (void);
00035
00036
00037 inline void * malloc (size_t sz);
00038
00039
00040 static inline void free (void * ptr);
00041
00042 private:
00043
00044 Super theHeap;
00045
00046 typedef BigChunk<chunkSize, slotSize, LooseSlotHeap> chunkType;
00047
00048 inline void localFree (void * ptr);
00049
00050 void checkClassInvariant (void) {
00051 #ifndef NDEBUG
00052 assert (inUse >= 0);
00053 assert (inUse <= space);
00054 assert (lastIndex >= 0);
00055 assert (lastIndex <= emptyFraction);
00056
00057 int localInUse = 0;
00058 int localSpace = 0;
00059 for (int i = 0; i < emptyFraction + 1; i++) {
00060 chunkType * ch = myChunks[i];
00061 while (ch != NULL) {
00062 assert (ch->getHeap() == this);
00063 localInUse += ch->getNumSlotsInUse();
00064 localSpace += ch->getNumSlots();
00065 ch = ch->getNext();
00066 }
00067 }
00068 assert (localSpace == space);
00069 assert (localInUse == inUse);
00070 #endif
00071 }
00072
00073
00074
00075
00076 static inline int getFullness (chunkType * ch);
00077
00078
00079
00080
00081 inline int update (chunkType * ch, int prevIndex);
00082
00083
00084
00085
00086 chunkType * myChunks[emptyFraction + 1];
00087
00088
00089 int lastIndex;
00090
00091
00092 int inUse;
00093
00094
00095 int space;
00096 };
00097
00098
00099 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00100 LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::LooseSlotHeap (void)
00101 : space (0),
00102 inUse (0),
00103 lastIndex (emptyFraction - 1)
00104 {
00105
00106 for (int i = 0; i < emptyFraction + 1; i++) {
00107 myChunks[i] = NULL;
00108 }
00109 }
00110
00111
00112 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00113 LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::~LooseSlotHeap (void)
00114 {
00115
00116 chunkType * ch, * tmp;
00117 for (int i = 0; i < emptyFraction + 1; i++) {
00118 ch = myChunks[i];
00119 while (ch != NULL) {
00120 tmp = ch;
00121 ch = ch->getNext();
00122 theHeap.free (tmp);
00123 }
00124 }
00125 }
00126
00127
00128 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00129 int LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::getFullness (chunkType * ch)
00130 {
00131 int fullness = (emptyFraction * ch->getNumSlotsInUse())/ch->getNumSlots();
00132
00133 return fullness;
00134 }
00135
00136
00137 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00138 void * LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::malloc (size_t sz)
00139 {
00140 checkClassInvariant();
00141
00142 assert (sz <= slotSize);
00143 void * ptr = NULL;
00144 chunkType * ch = NULL;
00145
00146
00147 lastIndex = emptyFraction - 1;
00148 while (lastIndex >= 0) {
00149 ch = myChunks[lastIndex];
00150 if (ch == NULL) {
00151 lastIndex--;
00152 } else {
00153
00154 break;
00155 }
00156 }
00157 if (lastIndex < 0) {
00158 assert (ch == NULL);
00159
00160 assert ((space - inUse) == 0);
00161
00162 printf ("!!!\n");
00163 ch = (chunkType*) theHeap.malloc (chunkSize);
00164 ch->setHeap (this);
00165 assert (ch->getNumSlotsFree() > 0);
00166 printf ("Super malloc %d\n", chunkSize);
00167 lastIndex = getFullness(ch);
00168 register chunkType*& head = myChunks[lastIndex];
00169 assert (head == NULL);
00170 ch->setPrev (NULL);
00171 ch->setNext (NULL);
00172 head = ch;
00173 inUse += ch->getNumSlotsInUse();
00174 space += ch->getNumSlots();
00175 assert (ch->getNumSlotsFree() <= ch->getNumSlots());
00176
00177 assert (ch->getNumSlotsFree() == ch->getNumSlots());
00178 printf ("Space, in use was %d, %d\n", space, inUse);
00179 printf ("Space, in use NOW %d, %d\n", space, inUse);
00180 }
00181 assert (ch != NULL);
00182 assert (ch->getNumSlotsFree() > 0);
00183 int prevFullness = getFullness (ch);
00184 int prevInUse = ch->getNumSlotsInUse();
00185 assert (ch->getHeap() == this);
00186 ptr = ch->getSlot();
00187 inUse++;
00188 assert (prevInUse + 1 == ch->getNumSlotsInUse());
00189 int newFullness = getFullness (ch);
00190 if (prevFullness != newFullness) {
00191 int n = update (ch, prevFullness);
00192 assert (n == newFullness);
00193 }
00194 chunkType * bch = (chunkType *) chunkType::getChunk(ptr);
00195 assert (bch == ch);
00196 assert (ptr != NULL);
00197 checkClassInvariant();
00198 return ptr;
00199 }
00200
00201
00202 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00203 void LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::free (void * ptr) {
00204 chunkType * ch
00205 = (chunkType *) chunkType::getChunk (ptr);
00206 assert (ch != NULL);
00207 (ch->getHeap())->localFree (ptr);
00208 }
00209
00210
00211 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00212 void LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::localFree (void * ptr) {
00213 checkClassInvariant();
00214 printf ("free! (in use = %d, space = %d)\n", inUse, space);
00215
00216 chunkType * ch
00217 = (chunkType *) chunkType::getChunk (ptr);
00218 assert (ch != NULL);
00219 assert (ch->getHeap() == this);
00220 int prevFullness = getFullness (ch);
00221 int prevInUse = ch->getNumSlotsInUse();
00222 ch->putSlot (ptr);
00223 inUse--;
00224 assert (prevInUse - 1 == ch->getNumSlotsInUse());
00225 checkClassInvariant();
00226 int newIndex = getFullness (ch);
00227 if (prevFullness != newIndex) {
00228 int n = update (ch, prevFullness);
00229 assert (n == newIndex);
00230 }
00231
00232
00233 if ((space - inUse > 2 * chunkSize/slotSize)
00234 && (emptyFraction * (space - inUse) > space)) {
00235 printf ("RETURNING A CHUNK!\n");
00236
00237 int emptyIndex = 0;
00238 ch = NULL;
00239 while (emptyIndex < emptyFraction) {
00240 ch = myChunks[emptyIndex];
00241 if (ch != NULL)
00242 break;
00243 emptyIndex++;
00244 }
00245 assert (ch != NULL);
00246 checkClassInvariant();
00247 ch->setHeap (NULL);
00248
00249 myChunks[emptyIndex] = myChunks[emptyIndex]->getNext();
00250 if (myChunks[emptyIndex] != NULL) {
00251 myChunks[emptyIndex]->setPrev (NULL);
00252 }
00253 ch->setPrev (NULL);
00254 ch->setNext (NULL);
00255
00256 assert (ch->getNumSlotsFree() >= 0);
00257 assert (ch->getNumSlots() >= ch->getNumSlotsFree());
00258 printf ("Updating space & in use: was %d, %d (slots in use = %d)\n",
00259 space, inUse, ch->getNumSlotsInUse());
00260 space -= ch->getNumSlots();
00261 inUse -= ch->getNumSlotsInUse();
00262 printf ("Updating space & in use: NOW %d, %d\n", space, inUse);
00263 theHeap.free (ch);
00264 checkClassInvariant();
00265 }
00266 checkClassInvariant();
00267 }
00268
00269
00270
00271
00272 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00273 int LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::update (chunkType * ch, int prevIndex)
00274 {
00275
00276 #ifndef NDEBUG
00277 chunkType * bch = myChunks[prevIndex];
00278 while (bch != NULL) {
00279 if (bch == ch)
00280 break;
00281 bch = bch->getNext();
00282 }
00283 assert (bch == ch);
00284 #endif
00285 int newIndex = getFullness(ch);
00286
00287
00288
00289 if (ch == myChunks[prevIndex]) {
00290 myChunks[prevIndex] = myChunks[prevIndex]->getNext();
00291 }
00293 if (ch->getPrev() != NULL) {
00294 ch->getPrev()->setNext(ch->getNext());
00295 }
00296 if (ch->getNext() != NULL) {
00297 ch->getNext()->setPrev(ch->getPrev());
00298 }
00299
00300 chunkType*& head = myChunks[newIndex];
00301 ch->setPrev (NULL);
00302 ch->setNext (head);
00303 if (head != NULL) {
00304 head->setPrev(ch);
00305 }
00306 head = ch;
00307
00308 #ifndef NDEBUG
00309 bch = myChunks[newIndex];
00310 while (bch != NULL) {
00311 if (bch == ch)
00312 break;
00313 bch = bch->getNext();
00314 }
00315 assert (bch == ch);
00316 #endif
00317 return newIndex;
00318 }
00319
00320
00321
00322 #endif