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