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
00032 #ifndef _SEGHEAP_H_
00033 #define _SEGHEAP_H_
00034
00059 #include <assert.h>
00060 #include "bitstring.h"
00061
00062 namespace HL {
00063
00064 template <int NumBins,
00065 int (*getSizeClass) (const size_t),
00066 size_t (*getClassMaxSize) (const int),
00067 class LittleHeap,
00068 class BigHeap>
00069 class SegHeap : public LittleHeap {
00070 private:
00071
00072 typedef int (*scFunction) (const size_t);
00073 typedef size_t (*csFunction) (const int);
00074
00075 public:
00076
00077 inline SegHeap (void)
00078 : memoryHeld (0),
00079 maxObjectSize (((csFunction) getClassMaxSize) (NumBins - 1))
00080 {
00081 for (int i = 0; i < NUM_ULONGS; i++) {
00082 binmap[i] = 0;
00083 }
00084 }
00085
00086 inline ~SegHeap (void) {}
00087
00088 inline size_t getMemoryHeld (void) const {
00089 return memoryHeld;
00090 }
00091
00092
00093 size_t getSize (void * ptr) {
00094 return LittleHeap::getSize (ptr);
00095 }
00096
00097 inline void * malloc (const size_t sz) {
00098 void * ptr = NULL;
00099 if (sz > maxObjectSize) {
00100 goto GET_MEMORY;
00101 }
00102
00103 {
00104 const int sc = ((scFunction) getSizeClass)(sz);
00105 assert (sc >= 0);
00106 assert (sc < NumBins);
00107 int idx = sc;
00108 int block = idx2block (idx);
00109 unsigned long map = binmap[block];
00110 unsigned long bit = idx2bit (idx);
00111
00112 for (;;) {
00113 if (bit > map || bit == 0) {
00114 do {
00115 if (++block >= NUM_ULONGS) {
00116 goto GET_MEMORY;
00117
00118 }
00119 } while ( (map = binmap[block]) == 0);
00120
00121 idx = block << SHIFTS_PER_ULONG;
00122 bit = 1;
00123 }
00124
00125 while ((bit & map) == 0) {
00126 bit <<= 1;
00127 assert(bit != 0);
00128 idx++;
00129 }
00130
00131 assert (idx < NumBins);
00132 ptr = myLittleHeap[idx].malloc (sz);
00133
00134 if (ptr == NULL) {
00135 binmap[block] = map &= ~bit;
00136 idx++;
00137 bit <<= 1;
00138 } else {
00139 return ptr;
00140 }
00141 }
00142 }
00143
00144 GET_MEMORY:
00145 if (ptr == NULL) {
00146
00147
00148 ptr = bigheap.malloc (sz);
00149 }
00150
00151 return ptr;
00152 }
00153
00154
00155 inline void free (void * ptr) {
00156
00157 const size_t objectSize = getSize(ptr);
00158 if (objectSize > maxObjectSize) {
00159
00160 bigheap.free (ptr);
00161 } else {
00162 int objectSizeClass = ((scFunction) getSizeClass) (objectSize);
00163 assert (objectSizeClass >= 0);
00164 assert (objectSizeClass < NumBins);
00165
00166 assert (getClassMaxSize(objectSizeClass) >= objectSize);
00167 #if 1
00168 while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) {
00169 objectSizeClass--;
00170 }
00171 #endif
00172 assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize);
00173 if (objectSizeClass > 0) {
00174 assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1));
00175 }
00176
00177
00178 myLittleHeap[objectSizeClass].free (ptr);
00179 mark_bin (objectSizeClass);
00180 memoryHeld += objectSize;
00181 }
00182 }
00183
00184
00185 void clear (void) {
00186 int i;
00187 for (i = 0; i < NumBins; i++) {
00188 myLittleHeap[i].clear();
00189 }
00190 for (int j = 0; j < NUM_ULONGS; j++) {
00191 binmap[j] = 0;
00192 }
00193
00194 bigheap.clear();
00195 memoryHeld = 0;
00196 }
00197
00198 private:
00199
00200 enum { BITS_PER_ULONG = 32 };
00201 enum { SHIFTS_PER_ULONG = 5 };
00202 enum { MAX_BITS = (NumBins + BITS_PER_ULONG - 1) & ~(BITS_PER_ULONG - 1) };
00203
00204
00205 private:
00206
00207 static inline int idx2block (int i) {
00208 int blk = i >> SHIFTS_PER_ULONG;
00209 assert (blk < NUM_ULONGS);
00210 assert (blk >= 0);
00211 return blk;
00212 }
00213
00214 static inline unsigned long idx2bit (int i) {
00215 unsigned long bit = ((1U << ((i) & ((1U << SHIFTS_PER_ULONG)-1))));
00216 return bit;
00217 }
00218
00219
00220 protected:
00221
00222 BigHeap bigheap;
00223
00224 enum { NUM_ULONGS = MAX_BITS / BITS_PER_ULONG };
00225 unsigned long binmap[NUM_ULONGS];
00226
00227 inline int get_binmap (int i) const {
00228 return binmap[i >> SHIFTS_PER_ULONG] & idx2bit(i);
00229 }
00230
00231 inline void mark_bin (int i) {
00232 binmap[i >> SHIFTS_PER_ULONG] |= idx2bit(i);
00233 }
00234
00235 inline void unmark_bin (int i) {
00236 binmap[i >> SHIFTS_PER_ULONG] &= ~(idx2bit(i));
00237 }
00238
00239 size_t memoryHeld;
00240
00241 const size_t maxObjectSize;
00242
00243
00244 LittleHeap myLittleHeap[NumBins];
00245
00246 };
00247
00248 };
00249
00250
00269 namespace HL {
00270
00271 template <int NumBins,
00272 int (*getSizeClass) (const size_t),
00273 size_t (*getClassMaxSize) (const int),
00274 class LittleHeap,
00275 class BigHeap>
00276 class StrictSegHeap :
00277 public SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap>
00278 {
00279 private:
00280
00281 typedef SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap> super;
00282
00283 typedef int (*scFunction) (const size_t);
00284 typedef size_t (*csFunction) (const int);
00285
00286 public:
00287
00288 void freeAll (void) {
00289 int i;
00290 for (i = 0; i < NumBins; i++) {
00291 const size_t sz = ((csFunction) getClassMaxSize)(i);
00292 void * ptr;
00293 while ((ptr = super::myLittleHeap[i].malloc (sz)) != NULL) {
00294 super::bigheap.free (ptr);
00295 }
00296 }
00297 for (int j = 0; j < super::NUM_ULONGS; j++) {
00298 super::binmap[j] = 0;
00299 }
00300 super::memoryHeld = 0;
00301 }
00302
00303
00309 inline void * malloc (const size_t sz) {
00310 void * ptr = NULL;
00311 if (sz <= super::maxObjectSize) {
00312 const int sizeClass = ((scFunction) getSizeClass) (sz);
00313 assert (sizeClass >= 0);
00314 assert (sizeClass < NumBins);
00315 ptr = super::myLittleHeap[sizeClass].malloc (sz);
00316 }
00317 if (!ptr) {
00318 ptr = super::bigheap.malloc (sz);
00319 }
00320 return ptr;
00321 }
00322
00323 inline void free (void * ptr) {
00324 const size_t objectSize = super::getSize(ptr);
00325 if (objectSize > super::maxObjectSize) {
00326 super::bigheap.free (ptr);
00327 } else {
00328 int objectSizeClass = ((scFunction) getSizeClass) (objectSize);
00329 assert (objectSizeClass >= 0);
00330 assert (objectSizeClass < NumBins);
00331
00332 assert (getClassMaxSize(objectSizeClass) >= objectSize);
00333 while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) {
00334 objectSizeClass--;
00335 }
00336 assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize);
00337 if (objectSizeClass > 0) {
00338 assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1));
00339 }
00340
00341 super::myLittleHeap[objectSizeClass].free (ptr);
00342 super::memoryHeld += objectSize;
00343 }
00344 }
00345
00346 };
00347
00348 };
00349
00350
00351 #endif