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
00033 #ifndef _COALESCEABLEHEAP_H_
00034 #define _COALESCEABLEHEAP_H_
00035
00036 #include <assert.h>
00037
00038 #define MULTIPLE_HEAP_SUPPORT 0
00039
00045 namespace HL {
00046
00047 template <class SuperHeap>
00048 class RequireCoalesceable : public SuperHeap {
00049 public:
00050
00051
00052 inline static int getHeap (void * ptr) { return Header::getHeader(ptr)->getHeap(); }
00053 inline static void setHeap (void * ptr, int h) { Header::getHeader(ptr)->setHeap(h); }
00054 inline static int getPrevHeap (void * ptr) { return Header::getHeader(ptr)->getPrevHeap(); }
00055 inline static void setPrevHeap (void * ptr, int h) { Header::getHeader(ptr)->setPrevHeap(h); }
00056
00057 inline static size_t getSize (const void * ptr) { return Header::getHeader(ptr)->getSize(); }
00058
00059 inline static void setSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setSize(sz); }
00060 inline static size_t getPrevSize (void * ptr) { return Header::getHeader(ptr)->getPrevSize(); }
00061 inline static void setPrevSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setPrevSize(sz); }
00062 inline static void markFree (void * ptr) { Header::getHeader(ptr)->markFree(); }
00063 inline static void markInUse (void * ptr) { Header::getHeader(ptr)->markInUse(); }
00064 inline static void markPrevInUse (void * ptr) { Header::getHeader(ptr)->markPrevInUse(); }
00065 inline static void markMmapped (void * ptr) { Header::getHeader(ptr)->markMmapped(); }
00066 inline static int isFree (void * ptr) { return Header::getHeader(ptr)->isFree(); }
00067 inline static int isPrevFree (void * ptr) { return Header::getHeader(ptr)->isPrevFree(); }
00068 inline static int isMmapped (void * ptr) { return Header::getHeader(ptr)->isMmapped(); }
00069 inline static void * getNext (const void * ptr) { return Header::getHeader(ptr)->getNext(); }
00070 inline static void * getPrev (const void * ptr) { return Header::getHeader(ptr)->getPrev(); }
00071
00072
00073 class Header {
00074 friend class RequireCoalesceable<SuperHeap>;
00075 public:
00076
00077
00078
00079
00080
00081 inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
00082 *((Header *) buf) = Header (prevsz, sz);
00083 Header * nextHeader = (Header *) ((char *) ((Header *) buf + 1) + sz);
00084
00085
00086 nextHeader->setPrevSize (sz);
00087
00088 return ((Header *) buf + 1);
00089 }
00090
00091
00092 inline void sanityCheck (void) {
00093 #ifndef NDEBUG
00094 int headerSize = sizeof(Header);
00095 assert (headerSize <= sizeof(double));
00096 assert (getSize() == getNextHeader()->getPrevSize());
00097 assert (isFree() == getNextHeader()->isPrevFree());
00098 assert (getNextHeader()->getPrev() == getObject(this));
00099 #if 0
00100 if (isPrevFree()) {
00101 assert (getPrevSize() == getHeader(getPrev())->getSize());
00102 }
00103 #endif
00104 #endif
00105 }
00106
00107
00108 inline static Header * getHeader (const void * ptr) { return ((Header *) ptr - 1); }
00109
00110
00111 inline static void * getObject (const Header * hd) { return (void *) (hd + 1); }
00112
00113 inline void setSize (const size_t sz) { _size = sz; }
00114 inline void setPrevSize (const size_t sz){ _prevSize = sz; }
00115
00116
00117 inline size_t getPrevSize (void) const { return _prevSize; }
00118
00119 inline void markFree (void) {
00120
00121 getNextHeader()->markPrevFree();
00122 }
00123 inline void markInUse (void) {
00124
00125 getNextHeader()->markPrevInUse();
00126 }
00127 inline void markMmapped (void) { _isMmapped = IS_MMAPPED; }
00128 inline void markNotMmapped (void) { _isMmapped = NOT_MMAPPED; }
00129 inline int isFree (void) const {
00130
00131 return getNextHeader()->isPrevFree();
00132 }
00133 inline int isNextFree (void) const {
00134
00135 return getNextHeader()->getNextHeader()->isPrevFree();
00136 }
00137 inline int isMmapped (void) const { return (_isMmapped != NOT_MMAPPED); }
00138 inline void * getPrev (void) const {
00139
00140 return ((char *) this) - getPrevSize();
00141 }
00142 inline void * getNext (void) const {
00143
00144 return ((char *) (this + 2)) + getSize();
00145 }
00146
00147 inline void markPrevFree (void) { _prevStatus = PREV_FREE; }
00148 inline void markPrevInUse (void) { _prevStatus = PREV_INUSE; }
00149 inline int isPrevFree (void) const { return (_prevStatus != PREV_INUSE); }
00150 inline size_t getSize (void) const { return _size; }
00151
00152 #if MULTIPLE_HEAP_SUPPORT
00153 inline int getHeap (void) const { return _currHeap; }
00154 inline void setHeap (int h) { _currHeap = h; }
00155 inline int getPrevHeap (void) const { return _prevHeap; }
00156 inline void setPrevHeap (int h) { _prevHeap = h; }
00157 #else
00158 inline int getHeap (void) const { return 0; }
00159 inline void setHeap (int) { }
00160 inline int getPrevHeap (void) const { return 0; }
00161 inline void setPrevHeap (int) { }
00162 #endif
00163
00164
00165 private:
00166
00167 explicit inline Header (void) {}
00168 explicit inline Header (const size_t prevsz, const size_t sz)
00169 :
00170 _prevSize (prevsz),
00171 _size (sz),
00172
00173 _isMmapped (NOT_MMAPPED)
00174 #if MULTIPLE_HEAP_SUPPORT
00175 , _prevHeap (0),
00176 _currHeap (0)
00177 #endif
00178 {
00179 assert (sizeof(Header) <= sizeof(double));
00180 }
00181
00182 inline Header * getNextHeader (void) const {
00183
00184 return ((Header *) ((char *) (this + 1) + getSize()));
00185 }
00186
00187 #if !(MULTIPLE_HEAP_SUPPORT) // original
00188
00189
00190 enum { PREV_INUSE = 0, PREV_FREE = 1 };
00191 unsigned int _prevStatus : 1;
00192
00193
00194 enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
00195 unsigned int _isMmapped : 1;
00196
00197
00198 enum { NUM_BITS_STOLEN_FROM_PREVSIZE = 2 };
00199 size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
00200
00201
00202 enum { NUM_BITS_STOLEN_FROM_SIZE = 0 };
00203 size_t _size;
00204
00205
00206 #else // new support for scalability...
00207
00208
00209 enum { NUM_BITS_FOR_HEAP = 5 };
00210
00211 enum { NUM_BITS_STOLEN_FROM_SIZE = NUM_BITS_FOR_HEAP + 1 };
00212 enum { NUM_BITS_STOLEN_FROM_PREVSIZE = NUM_BITS_FOR_HEAP + 1 };
00213
00214
00215 enum { MAX_OBJECT_SIZE = 1 << (sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE) };
00216
00218
00219
00220 size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
00221
00222
00223 unsigned int _prevHeap : NUM_BITS_FOR_HEAP;
00224
00225
00226 enum { PREV_FREE = 0, PREV_INUSE = 1 };
00227 unsigned int _prevStatus : 1;
00228
00230
00231
00232 size_t _size : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE;
00233
00234
00235 unsigned int _currHeap : NUM_BITS_FOR_HEAP;
00236
00237
00238 enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
00239 unsigned int _isMmapped : 1;
00240
00241 #endif
00242 };
00243
00244 inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
00245 return Header::makeObject (buf, prevsz, sz);
00246 }
00247
00248 inline static Header * getHeader (const void * ptr) {
00249 return Header::getHeader (ptr);
00250 }
00251
00252 };
00253
00254
00260 template <class SuperHeap>
00261 class CoalesceableHeap : public RequireCoalesceable<SuperHeap> {
00262 public:
00263
00264 typedef typename RequireCoalesceable<SuperHeap>::Header Header;
00265
00266 inline CoalesceableHeap (void)
00267 { }
00268
00269 inline void * malloc (const size_t sz) {
00270 void * buf = SuperHeap::malloc (sz + sizeof(Header));
00271 if (buf) {
00272 Header * header = (Header *) buf;
00273
00274
00275
00276
00277
00278
00279 header->setSize (sz);
00280
00281
00282
00283 Header * nextHeader = (Header *) ((char *) (header + 1) + sz);
00284
00285 nextHeader->setPrevSize (sz);
00286
00287 #if 0
00288
00289
00290
00291
00292
00293 assert (header->isMmapped() == FALSE);
00294 assert (nextHeader->getSize() == 0);
00295 assert (!nextHeader->isFree());
00296 assert (!nextHeader->isPrevFree());
00297
00298 #else
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 header->markNotMmapped ();
00309
00310 nextHeader->setSize (0);
00311
00312
00313
00314
00315
00316
00317
00318 nextHeader->markInUse ();
00319 #endif
00320
00321
00322
00323 return (header + 1);
00324 }
00325 return NULL;
00326 }
00327
00328 inline void free (void * ptr) {
00329 assert (SuperHeap::isFree(ptr));
00330 SuperHeap::free ((Header *) ptr - 1);
00331 }
00332
00333
00334 };
00335
00336 };
00337
00338 #endif // _COALESCEABLEHEAP_H_
00339