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