00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _HLOBSTACK_H_
00031 #define _HLOBSTACK_H_
00032
00033
00034 #ifdef __cplusplus
00035
00036 #include <assert.h>
00037 #include <new>
00038
00044 namespace HL {
00045
00046 template <int ChunkSize, class SuperHeap>
00047 class ObstackHeap : public SuperHeap {
00048 public:
00049
00050 ObstackHeap (void)
00051 {
00052
00053 currentChunk = makeChunk (NULL, ChunkSize);
00054 currentBase = nextPos = (char *) (currentChunk + 1);
00055 assert (isValid());
00056 }
00057
00058 ~ObstackHeap (void) {
00059
00060 assert (isValid());
00061 ChunkHeader * ch = currentChunk;
00062 while (ch != NULL) {
00063 ChunkHeader * pch = ch->getPrevChunk();
00064
00065 SuperHeap::free (ch);
00066 ch = pch;
00067 }
00068 }
00069
00070
00071
00072 inline void * grow (size_t sz) {
00073
00074
00075 assert (isValid());
00076 if ((int) ((char *) currentChunk->getLimit() - (char *) nextPos) < sz) {
00077 ChunkHeader * newCurrent = copyToNew(sz);
00078 if (newCurrent == NULL)
00079 return NULL;
00080 #if 0
00081
00082 if (deleteChunk != NULL) {
00083 SuperHeap::free (deleteChunk);
00084 }
00085 #endif
00086 assert (isValid());
00087 }
00088 assert (((int) ((char *) currentChunk->getLimit() - (char *) nextPos) >= sz));
00089 assert ((char *) (sz + nextPos) <= currentChunk->getLimit());
00090
00091 void * prevNextPos = nextPos;
00092 nextPos += sz;
00093 assert (isValid());
00094 return prevNextPos;
00095 }
00096
00097
00098 inline void * malloc (size_t sz) {
00099 assert (isValid());
00100 if (currentChunk == NULL) {
00101 return NULL;
00102 }
00103
00104
00105
00106 if ((int) ((char *) currentChunk->getLimit() - (char *) nextPos) < sz) {
00107
00108 currentChunk = makeChunk (currentChunk, sz);
00109 if (currentChunk == NULL) {
00110 return NULL;
00111 }
00112 currentBase = nextPos = (char *) (currentChunk + 1);
00113 assert (isValid());
00114 }
00115 assert (((int) ((char *) currentChunk->getLimit() - (char *) nextPos) >= sz));
00116 assert ((char *) (sz + nextPos) <= currentChunk->getLimit());
00117
00118 currentBase = nextPos;
00119 nextPos += sz;
00120 void * ptr = currentBase;
00121 finalize();
00122 assert (isValid());
00123 return (void *) ptr;
00124 }
00125
00126
00127
00128 inline void free (void * ptr) {
00129 assert (isValid());
00130
00131
00132 while (currentChunk != NULL &&
00133 (((char *) currentChunk > (char *) ptr) ||
00134 ((char *) currentChunk->getLimit() < (char *) ptr))) {
00135 ChunkHeader * pch = currentChunk;
00136 currentChunk = currentChunk->getPrevChunk();
00137 SuperHeap::free (pch);
00138 }
00139 if (currentChunk != NULL) {
00140 currentBase = nextPos = (char *) ptr;
00141 assert (isValid());
00142 } else {
00143 if (ptr != NULL) {
00144
00145
00146 abort();
00147 } else {
00148
00149 currentChunk = makeChunk (NULL, ChunkSize);
00150 currentBase = nextPos = (char *) (currentChunk + 1);
00151 assert (isValid());
00152 }
00153 }
00154 }
00155
00156
00157 inline void * getObjectBase (void) {
00158 assert (isValid());
00159 return currentBase;
00160 }
00161
00162
00163 inline void finalize (void) {
00164 assert (isValid());
00165 nextPos = (char *) align((int) nextPos);
00166 currentBase = nextPos;
00167 assert (isValid());
00168 }
00169
00170
00171 private:
00172
00173
00174 inline int objectSize (void) {
00175 int diff = (int) (nextPos - currentBase);
00176 assert (diff >= 0);
00177 return diff;
00178 }
00179
00180
00181 int isValid (void) {
00182
00183 #ifndef NDEBUG
00184 bool c1 = (currentBase <= nextPos);
00185 assert (c1);
00186 bool c2 = (nextPos <= currentChunk->getLimit());
00187 assert (c2);
00188 bool c3 = ((char *) currentChunk <= currentChunk->getLimit());
00189 assert (c3);
00190 bool c4 = ((char *) currentChunk <= currentBase);
00191 assert (c4);
00192 bool c5 = (currentChunk != currentChunk->getPrevChunk());
00193 assert (c5);
00194 bool c6 = (objectSize() >= 0);
00195 assert (c6);
00196 return (c1 && c2 && c3 && c4 && c5 && c6);
00197 #else
00198 return 1;
00199 #endif
00200 }
00201
00202
00203 class ChunkHeader {
00204 public:
00205 inline ChunkHeader (ChunkHeader * prev, size_t sz)
00206 : _pastEnd ((char *) (this + 1) + sz),
00207 _prevChunk (prev)
00208 {}
00209
00210
00211 inline char * getLimit (void) { return _pastEnd; }
00212
00213
00214 inline ChunkHeader * getPrevChunk (void) { return _prevChunk; }
00215
00216 private:
00217
00218 char * _pastEnd;
00219
00220
00221 ChunkHeader * _prevChunk;
00222 };
00223
00224
00225 inline static size_t align (int sz) {
00226 return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
00227 }
00228
00229
00230 inline ChunkHeader * makeChunk (ChunkHeader * ch, size_t sz) {
00231
00232 size_t allocSize
00233 = align((sz > ChunkSize - sizeof(ChunkHeader)) ? sz : ChunkSize - sizeof(ChunkHeader));
00234
00235 ChunkHeader * newChunk
00236 = new (SuperHeap::malloc (sizeof(ChunkHeader) + allocSize)) ChunkHeader (ch, allocSize);
00237 return newChunk;
00238 }
00239
00240
00241
00242
00243 inline ChunkHeader * copyToNew (size_t sz) {
00244 size_t obj_size = objectSize();
00245 size_t new_size = obj_size + sz + (obj_size >> 3) + 100;
00246
00247 ChunkHeader * newChunk;
00248 #if 0
00249
00250 ChunkHeader * deleteChunk = NULL;
00251
00252
00253 if (currentBase == (char *) (currentChunk + 1)) {
00254 newChunk = makeChunk (currentChunk->getPrevChunk(), new_size);
00255 deleteChunk = currentChunk;
00256 } else {
00257 newChunk = makeChunk (currentChunk, new_size);
00258 }
00259 #else
00260 newChunk = makeChunk (currentChunk, new_size);
00261 #endif
00262 if (newChunk == NULL) {
00263 currentChunk = NULL;
00264 return NULL;
00265 }
00266
00267 memcpy ((char *) (newChunk + 1), currentBase, obj_size);
00268 currentChunk = newChunk;
00269 currentBase = (char *) (currentChunk + 1);
00270 nextPos = currentBase + obj_size;
00271 #if 0
00272 if (deleteChunk != NULL) {
00273 SuperHeap::free (deleteChunk);
00274 }
00275 #endif
00276 return currentChunk;
00277 }
00278
00279
00280
00281 char * currentBase;
00282
00283
00284 char * nextPos;
00285
00286
00287 ChunkHeader * currentChunk;
00288
00289 };
00290
00291 #endif // __cplusplus
00292
00293
00294 struct obstack {
00295 void * _dummy[3];
00296 };
00297
00298 };
00299
00300 #endif // _HLOBSTACK_H_