00001
00002
00003 #ifndef _ALIGNEDCHUNK_H_
00004 #define _ALIGNEDCHUNK_H_
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 #include <stdlib.h>
00031 #include <malloc.h>
00032 #include <assert.h>
00033
00034 #include "bitindex.h"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 namespace HL {
00057
00058 template <int chunkSize, class Super>
00059 class AlignHeap {
00060 public:
00061 inline void * malloc (size_t sz) {
00062
00063 void * buf = ::malloc (sz + chunkSize);
00064
00065 void * alignedBuf = (void *) (((unsigned long) buf + sizeof(unsigned long) + chunkSize - 1) & -chunkSize);
00066
00067 assert ((unsigned long) alignedBuf - (unsigned long) buf > sizeof(unsigned long));
00068 *((unsigned long *) alignedBuf - 1) = (unsigned long) buf;
00069 return alignedBuf;
00070 }
00071
00072 void free (void * ptr) {
00073
00074 ::free ((void *) *((unsigned long *) ptr - 1));
00075 }
00076 };
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 template <int chunkSize, int slotSize>
00094 class AlignedChunk {
00095 public:
00096
00097 AlignedChunk (void)
00098 : prev (NULL),
00099 next (NULL),
00100 status (ACQUIRED),
00101 inUse (0)
00102 {
00103
00104 assert (getNumSlots() * slotSize + sizeof(AlignedChunk) <= chunkSize);
00105
00106 assert (slotSize == align(slotSize));
00107
00108 freeBitmap = 0;
00109
00110 BitIndex::set (freeBitmap, 0);
00111 emptyBitmap = freeBitmap;
00112 }
00113
00114 ~AlignedChunk (void)
00115 {}
00116
00117
00118
00119
00120
00121
00122 void * getSlot (void) {
00123 RETRY_UNSET:
00124 unsigned long currBitmap = freeBitmap;
00125
00126
00127 if (currBitmap == (unsigned long) -1) {
00128 assert (inUse == getNumSlots());
00129 return NULL;
00130 }
00131
00132
00133
00134 int bitIndex;
00135 unsigned long oneBit = (~currBitmap) & (-((signed long) ~currBitmap));
00136 assert (oneBit != 0);
00137 bitIndex = BitIndex::msb (oneBit);
00138 if (bitIndex > getNumSlots()) {
00139 assert (inUse == getNumSlots());
00140 return NULL;
00141 }
00142 assert (inUse < getNumSlots());
00143 assert (bitIndex < getNumSlots() + 1);
00144
00145 unsigned long oldBitmap = currBitmap;
00146 BitIndex::set (currBitmap, bitIndex);
00147 unsigned long updatedBitmap = InterlockedExchange ((long *) &freeBitmap, currBitmap);
00148 if (updatedBitmap == oldBitmap) {
00149
00150
00151 char * start = (char *) ((unsigned long) this & -chunkSize);
00152 inUse++;
00153 return start + slotSize * (getNumSlots() - bitIndex);
00154 }
00155
00156
00157 goto RETRY_UNSET;
00158 }
00159
00160
00161
00162 inline int putSlot (void * ptr) {
00163 assert (inUse >= 1);
00164 AlignedChunk * ch = getChunk (ptr);
00165 assert (ch == this);
00166
00167
00168
00169 char * start = (char *) ((unsigned long) ptr & -chunkSize);
00170 int bitIndex = getNumSlots() - (((unsigned long) ((char *) ptr - start)) / slotSize);
00171 RETRY_RESET:
00172 unsigned long currBitmap = freeBitmap;
00173 unsigned long oldBitmap = currBitmap;
00174 BitIndex::reset (currBitmap, bitIndex);
00175 unsigned long updatedBitmap = InterlockedExchange ((long *) &freeBitmap, currBitmap);
00176 if (updatedBitmap == oldBitmap) {
00177
00178 inUse--;
00179 assert ((inUse != 0) || (currBitmap == emptyBitmap));
00180 assert ((inUse == 0) || (currBitmap != emptyBitmap));
00181
00182 if (currBitmap == emptyBitmap) {
00183 assert (inUse == 0);
00184 return 1;
00185 } else {
00186 assert (inUse > 0);
00187 return 0;
00188 }
00189 }
00190
00191 goto RETRY_RESET;
00192 }
00193
00194
00195
00196 inline static int getNumSlots (void) {
00197 return 31;
00198 }
00199
00200 inline int isReleased (void) {
00201 return (status == RELEASED);
00202 }
00203
00204 inline void acquire (void) {
00205 assert (status == RELEASED);
00206 status = ACQUIRED;
00207 }
00208
00209 inline void release (void) {
00210 assert (status == ACQUIRED);
00211 status = RELEASED;
00212 }
00213
00214
00215 inline static AlignedChunk * getChunk (void * slot) {
00216
00217
00218 assert ((chunkSize & (chunkSize - 1)) == 0);
00219
00220 char * start = (char *) ((unsigned long) slot & -chunkSize);
00221
00222 char * eob = (start + chunkSize);
00223
00224 char * headerPos = eob - sizeof(AlignedChunk);
00225 return (AlignedChunk *) headerPos;
00226 }
00227
00228
00229
00230 AlignedChunk * getNext (void) { return next; }
00231 AlignedChunk * getPrev (void) { return prev; }
00232 void setNext (AlignedChunk * p) { next = p; }
00233 void setPrev (AlignedChunk * p) { prev = p; }
00234
00235 private:
00236
00237 enum { RELEASED = 0, ACQUIRED = 1 };
00238
00239 static inline size_t align (size_t sz) {
00240 return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
00241 }
00242
00243 int inUse;
00244 unsigned long freeBitmap;
00245 unsigned long emptyBitmap;
00246 int status;
00247 AlignedChunk * prev;
00248 AlignedChunk * next;
00249 };
00250
00251
00252
00253
00254 template <int maxFree, int chunkSize, int slotSize, class Super>
00255 class AlignedChunkHeap : public Super {
00256 public:
00257
00258 AlignedChunkHeap (void)
00259 : chunkList (NULL),
00260 length (0)
00261 {}
00262
00263 virtual ~AlignedChunkHeap (void)
00264 {
00265 chunkType * ch, * tmp;
00266 ch = chunkList;
00267 while (ch != NULL) {
00268 tmp = ch;
00269 ch = ch->getNext();
00270 assert (tmp->isReleased());
00271 Super::free ((char *) ((unsigned long) tmp & -chunkSize));
00272 }
00273 }
00274
00275
00276 inline void * malloc (size_t sz)
00277 {
00278 assert (sz == chunkSize);
00279 chunkType * ch;
00280
00281
00282 if (chunkList != NULL) {
00283 ch = chunkList;
00284 chunkList = chunkList->getNext();
00285 length--;
00286 ch->acquire();
00287 } else {
00288
00289 void * buf = Super::malloc (chunkSize);
00290
00291 assert ((unsigned long) buf == ((unsigned long) buf & -chunkSize));
00292
00293
00294 ch = new (chunkType::getChunk (buf)) chunkType;
00295 }
00296
00297 assert (!ch->isReleased());
00298 return (void *) ((unsigned long) ch & -chunkSize);
00299 }
00300
00301
00302
00303 inline void free (void * ptr)
00304 {
00305 chunkType * ch = (chunkType *) AlignedChunk<chunkSize, slotSize>::getChunk(ptr);
00306 assert (ch->isReleased());
00307 if (length > maxFree) {
00308 Super::free ((void *) ((unsigned long) ch & -chunkSize));
00309 } else {
00310 ch->setNext (chunkList);
00311 chunkList = ch;
00312 length++;
00313 }
00314 }
00315
00316 size_t size (void * ptr) {
00317 return slotSize;
00318 }
00319
00320 private:
00321
00322 typedef AlignedChunk<chunkSize, slotSize> chunkType;
00323
00324 chunkType * chunkList;
00325 int length;
00326 };
00327
00328
00329
00330
00331
00332
00333
00334 template <int chunkSize, int slotSize, class Super>
00335 class AlignedSlotHeap : public Super {
00336 public:
00337
00338 AlignedSlotHeap (void)
00339 : myChunk (NULL)
00340 {}
00341
00342 virtual ~AlignedSlotHeap (void) {
00343
00344 if (myChunk != NULL) {
00345 myChunk->release();
00346 Super::free ((void *) ((unsigned long) myChunk & -chunkSize));
00347 }
00348 }
00349
00350
00351
00352
00353 inline void * malloc (size_t sz) {
00354 assert (sz <= slotSize);
00355 void * ptr = NULL;
00356 while (ptr == NULL) {
00357 if (myChunk == NULL) {
00358 myChunk = AlignedChunk<chunkSize, slotSize>::getChunk(Super::malloc (chunkSize));
00359 }
00360 ptr = myChunk->getSlot();
00361 if (ptr == NULL) {
00362
00363
00364 myChunk->release();
00365 myChunk = NULL;
00366 }
00367 };
00368 return ptr;
00369 }
00370
00371
00372
00373
00374 inline void free (void * ptr)
00375 {
00376
00377 AlignedChunk<chunkSize, slotSize> * ch = AlignedChunk<chunkSize, slotSize>::getChunk (ptr);
00378
00379 int empty = ch->putSlot (ptr);
00380 if (empty && ch->isReleased()) {
00381 Super::free ((void *) ((unsigned long) ch & -chunkSize));
00382 }
00383 }
00384
00385 private:
00386
00387
00388 AlignedChunk<chunkSize, slotSize> * myChunk;
00389
00390 };
00391
00392
00393 template <int maxFree, int chunkSize, int slotSize, class Super>
00394 class AlignedChunkHeapFoo : public AlignedSlotHeap<chunkSize, slotSize, AlignedChunkHeap<maxFree, chunkSize, slotSize, Super> > {};
00395
00396 };
00397
00398 #endif