Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/experimental/looseslotheap.h
Ir a la documentación de este archivo.
00001 /* -*- C++ -*- */
00002 
00003 #ifndef _LOOSESLOTHEAP_H_
00004 #define _LOOSESLOTHEAP_H_
00005 
00006 #include <assert.h>
00007 
00008 #include "bigchunk.h"
00009 
00010 /*
00011   LooseSlotHeap: A "Loose" slot heap.
00012 
00013   malloc returns objects of size slotSize, allocated from the super heap
00014   in chunkSize units.
00015 
00016   free returns objects of size slotSize.
00017 
00018   When the slot heap is at least 1/emptyFraction empty, a
00019   chunk that is at least that empty is freed to the super heap.
00020   Note that the chunk's memory MAY NOT SAFELY be recycled in toto --
00021   it must be parceled out using the chunk interface.
00022 
00023   The intent of this heap is to allow mostly-empty chunks to move up
00024   to a staging area (the super heap) where they may be reused by other
00025   "loose" slot heaps.
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   // Get a slotSize object.
00037   inline void * malloc (size_t sz);
00038 
00039   // Free a slotSize object.
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                 // Now check to make sure that inUse & space are correct.
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   // How full is this block?
00074         //   0 == empty to no more than 1/emptyFraction full.
00075         //   emptyFraction == completely full.
00076   static inline int getFullness (chunkType * ch);
00077     
00078         // Move a chunk, if necessary, into the right list
00079   // based on its emptiness.
00080         // Returns the index of which list it is put or left in.
00081         inline int update (chunkType * ch, int prevIndex);
00082 
00083   // The array of chunks, "radix sorted" by emptiness.
00084   // completely empty chunks are in index 0.
00085   // completely full chunks are in index emptyFraction.
00086   chunkType * myChunks[emptyFraction + 1];
00087 
00088   // The last index (from 0) in the above array that has a chunk.
00089   int lastIndex;
00090 
00091   // How much space is in use in all of the chunks.
00092   int inUse;
00093 
00094   // How much space there is (free or not) in all of the chunks.
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         // Initialize the chunk pointers (all initially empty).
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         // Free every chunk.
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         //printf ("numslots avail = %d, num slots total = %d, fullness = %d\n", ch->getNumSlotsFree(), ch->getNumSlots(), fullness);
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         //printf ("Loose malloc %d (slot size = %d)\n", sz, slotSize);
00142   assert (sz <= slotSize);
00143   void * ptr = NULL;
00144         chunkType * ch = NULL;
00145   // Always try to allocate from the most-full chunk (resetting
00146   // lastIndex as we go).
00147         lastIndex = emptyFraction - 1; // FIX ME!
00148   while (lastIndex >= 0) {
00149                 ch = myChunks[lastIndex];
00150     if (ch == NULL) {
00151       lastIndex--;
00152     } else {
00153       // Got one.
00154       break;
00155     }
00156   }
00157   if (lastIndex < 0) {
00158                 assert (ch == NULL);
00159     // There were no chunks available.
00160     assert ((space - inUse) == 0);
00161     // Make one with memory from the "super" heap.
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                 // FOR NOW!! FIX ME!!!
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   // Mark the slot in the chunk as free.
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   // If we are more than 1/emptyFraction empty,
00232   // return a mostly-empty chunk to the super heap.
00233   if ((space - inUse > 2 * chunkSize/slotSize)
00234                 && (emptyFraction * (space - inUse) > space)) {
00235                 printf ("RETURNING A CHUNK!\n");
00236                 // Find an empty chunk.
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     // Remove a chunk and give it to the super heap.
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                 // A sanity check on the chunk we're about to return.
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 // Move a chunk, if necessary, into the right list
00271 // based on its emptiness.
00272 template <int chunkSize, int slotSize, int emptyFraction, class Super>
00273 int LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::update (chunkType * ch, int prevIndex)
00274 {
00275   // Move this chunk if necessary.
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   // printf ("newIndex = %d\n", newIndex);
00287         // Reset last index (for simplicity). // FIX ME??
00288   // Remove the chunk from its current list.
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   // Add it to the newIndex list.
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         // Verify that the chunk is in the right list.
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
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'