Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/obstackreap.h
Ir a la documentación de este archivo.
00001 // -*- C++ -*-
00002 
00003 #ifndef _OBSTACKREAP_H_
00004 #define _OBSTACKREAP_H_
00005 
00006 #include <assert.h>
00007 
00008 /*
00009 
00010   ObstackReap layers obstack functionality on top of reaps.
00011 
00012   */
00013 
00014 #if WIN32
00015 #include <windows.h>
00016 #endif
00017 
00018 #include "dynarray.h"
00019 
00020 namespace ObstackReapNS {
00021 
00022 #if 0
00023         template <class ObjType>
00024   class DynamicArray {
00025   public:
00026     DynamicArray (void)
00027       : internalArray (0),
00028         internalArrayLength (0)
00029     {}
00030     
00031     ~DynamicArray (void)
00032     {
00033       clear();
00034     }
00035     
00036     // clear deletes everything in the array.
00037 
00038     inline void clear (void) {
00039       if (internalArray) {
00040         delete [] internalArray;
00041         internalArray = 0;
00042         internalArrayLength = 0;
00043         //printf ("\ninternalArrayLength %x = %d\n", this, internalArrayLength);
00044       }
00045     }
00046 
00047     // Read-only access to an array element;
00048     // asserts that this index is in range.
00049 
00050     inline const ObjType& operator[] (int index) const {
00051       assert (index < internalArrayLength);
00052       assert (index >= 0);
00053       return internalArray[index];
00054     }
00055 
00056     // Access a particular array index by reference,
00057     // growing the array if necessary.
00058 
00059     inline ObjType& operator[] (int index) {
00060       assert (index >= 0);
00061       if (index >= internalArrayLength) {
00062 
00063         // This index is beyond the current size of the array.
00064         // Grow the array by doubling and copying the old array into the new.
00065 
00066         const int newSize = index * 2 + 1;
00067         ObjType * arr = new ObjType[newSize];
00068         // printf ("grow! %d to %d\n", internalArrayLength, newSize);
00069 #if MALLOC_TRACE
00070         printf ("m %x %d\n", arr, newSize * sizeof(ObjType));
00071 #endif
00072         if (internalArray) {
00073           memcpy (arr, internalArray, internalArrayLength * sizeof(ObjType));
00074           delete [] internalArray;
00075 #if MALLOC_TRACE
00076           printf ("f %x\n", internalArray);
00077 #endif
00078         }
00079         internalArray = arr;
00080         internalArrayLength = newSize;
00081         // printf ("\ninternalArrayLength %x = %d\n", this, internalArrayLength);
00082       }
00083       return internalArray[index];
00084     }
00085 
00086     // trim informs the array that it is now only nelts long
00087     // as far as the client is concerned. This may trigger
00088     // shrinking of the array.
00089 
00090     inline void trim (int nelts) {
00091 
00092       // Halve the array if the number of elements
00093       // drops below one-fourth of the array size.
00094 
00095       if (internalArray) {
00096         if (nelts * 4 < internalArrayLength) {
00097           const int newSize = nelts * 2;
00098           ObjType * arr = new ObjType[newSize];
00099           // printf ("trim! %d to %d\n", internalArrayLength, newSize);
00100 #if MALLOC_TRACE
00101           printf ("m %x %d\n", arr, newSize * sizeof(ObjType));
00102 #endif
00103           memcpy (arr, internalArray, sizeof(ObjType) * nelts);
00104           delete [] internalArray;
00105 #if MALLOC_TRACE
00106           printf ("f %x\n", internalArray);
00107 #endif
00108           internalArray = arr;
00109           internalArrayLength = newSize;
00110         }
00111         assert (nelts <= internalArrayLength);
00112       }
00113     }
00114 
00115 
00116   private:
00117 
00118     // The pointer to the current array.
00119 
00120     ObjType * internalArray;
00121 
00122     // The length of the internal array, in elements.
00123         
00124     int internalArrayLength;
00125   };
00126 #endif
00127 
00128   template <class OBJTYPE>
00129   class DynStack {
00130   public:
00131     DynStack (void)
00132       : numItems (0)
00133     {
00134       items[0] = 0;
00135     }
00136 
00137     int length (void) const { return numItems; }
00138 
00139     inline void push (OBJTYPE * ptr) {
00140       numItems++;
00141       items[numItems] = ptr;
00142     }
00143 
00144     inline OBJTYPE * pop (void) {
00145       OBJTYPE * ptr = 0;
00146       if (numItems > 0) {
00147         ptr = items[numItems];
00148         numItems--;
00149         // The array has shrunk, so potentially trim it.
00150         items.trim (numItems + 1);
00151       }
00152       return ptr;
00153     }
00154 
00155     inline OBJTYPE * top (void) {
00156       OBJTYPE * ptr = NULL;
00157       if (numItems > 0) {
00158         ptr = items[numItems];
00159       }
00160       return ptr;
00161     }
00162 
00163     inline void clear (void) {
00164       items.clear();
00165     }
00166   
00167   private:
00168   
00169     // The number of items recorded above.
00170     // 0 == no items.
00171     // 1 == items[1] has the single item, etc.
00172     // i.e., we waste entry zero.
00173 
00174     int numItems;
00175 
00176     // The array of remembered objects.
00177 
00178     DynamicArray<OBJTYPE *> items;
00179   };
00180 
00181 };
00182 
00183 
00184 // Layers on top of a reap.
00185 
00186 template <class ReapType>
00187 class ObstackReap {
00188 public:
00189 
00190   ObstackReap (void)
00191   {
00192     currentReap = new ReapType;
00193     initCurrentObject();
00194   }
00195 
00196   ~ObstackReap (void) {
00197     ReapType * r;
00198     while ((r = reapStack.pop())) {
00199       delete r;
00200     }
00201     delete currentReap;
00202     delete currentObject;
00203   }
00204   
00205   inline void * malloc (size_t sz);
00206   inline void freeAfter (void * ptr);
00207   inline void freeAll (void);
00208   inline void * getObjectBase (void);
00209   inline void finalize (void);
00210   inline void * grow (size_t sz);
00211 
00212 private:
00213 
00214   inline void initCurrentObject (void);
00215 
00216   // Hide free.
00217   void free (void *);
00218 
00219   enum { INITIAL_OBJECT_SIZE = 8 * sizeof(double) };
00220 
00221   void * currentObject;
00222   char * currentObjectPosition;
00223   size_t currentObjectSize;
00224   size_t actualObjectSize;
00225   bool isCurrentObjectExposed;
00226   ReapType * currentReap;
00227   ObstackReapNS::DynStack<ReapType> reapStack;
00228 };
00229 
00230 
00231 template <class ReapType>
00232 void ObstackReap<ReapType>::initCurrentObject (void) {
00233   currentObject = currentReap->malloc (INITIAL_OBJECT_SIZE);
00234   currentObjectPosition = (char *) currentObject;
00235   currentObjectSize = 0;
00236   actualObjectSize = INITIAL_OBJECT_SIZE;
00237   isCurrentObjectExposed = false;
00238 }
00239 
00240 template <class ReapType>
00241 void * ObstackReap<ReapType>::malloc (size_t sz) {
00242   if (!isCurrentObjectExposed) {
00243     return currentReap->malloc (sz);
00244   } else {
00245     void * ptr = currentReap->realloc (currentObject, sz);
00246     reapStack.push (currentReap);
00247     currentReap = new ReapType;
00248     initCurrentObject();
00249     return ptr;
00250   }
00251 }
00252 
00253 template <class ReapType>
00254 void ObstackReap<ReapType>::freeAfter (void * ptr) {
00255   while (currentReap && (!currentReap->find(ptr))) {
00256     delete currentReap;
00257     currentReap = reapStack.pop();
00258   }
00259 }
00260 
00261 template <class ReapType>
00262 void ObstackReap<ReapType>::freeAll (void) {
00263   while (currentReap) {
00264     delete currentReap;
00265     currentReap = reapStack.pop();
00266   }
00267   currentHeap = new ReapType;
00268 }
00269 
00270 
00271 template <class ReapType>
00272 inline void * ObstackReap<ReapType>::getObjectBase (void) {
00273   isCurrentObjectExposed = true;
00274   return currentObject;
00275 }
00276 
00277 template <class ReapType>
00278 inline void ObstackReap<ReapType>::finalize (void) {
00279   if (isCurrentObjectExposed) {
00280     reapStack.push (currentReap);
00281     currentReap = new ReapType;
00282   }
00283   initCurrentObject();
00284 }
00285 
00286 template <class ReapType>
00287 inline void * ObstackReap<ReapType>::grow (size_t sz) {
00288 
00289   const int requestedObjectSize = currentObjectSize + sz;
00290 
00291   if (requestedObjectSize > actualObjectSize) {
00292     cout << "resize!\n";
00293     void * ptr = currentReap->realloc (currentObject, sz);
00294     currentObjectPosition = (char *) ptr + (currentObjectPosition - (char *) currentObject);
00295     if (isCurrentObjectExposed) {
00296       reapStack.push (currentReap);
00297       currentReap = new ReapType;
00298     }
00299     currentObject = ptr;
00300   }
00301 
00302   // Because calling grow can result in a new object,
00303   // the current object can be considered no longer exposed (if it was before).
00304 
00305   isCurrentObjectExposed = false;
00306   currentObjectSize += sz;
00307   char * oldPosition = currentObjectPosition;
00308   currentObjectPosition += sz;
00309   return oldPosition;
00310 }
00311 
00312 #endif
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'