00001
00002
00003 #ifndef _CHUNK_H_
00004 #define _CHUNK_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 <assert.h>
00031
00032 namespace HL {
00033
00034 template <int chunkSize, int slotSize>
00035 class Chunk {
00036 public:
00037
00038 inline Chunk (void);
00039
00040
00041
00042 inline void * getSlot (void);
00043 inline void putSlot (void *);
00044
00045
00046 inline static int getNumSlots (void);
00047
00048
00049 inline int getNumSlotsFree (void);
00050
00051
00052 inline int getNumSlotsInUse (void);
00053
00054
00055 inline static Chunk * getChunk (void *);
00056
00057 class ChunkBlock {
00058 public:
00059 void setChunk (Chunk * ch) { _myChunk = ch; }
00060 Chunk * getChunk (void) { return _myChunk; }
00061 void setNext (ChunkBlock * n) { _next = n; }
00062 ChunkBlock * getNext (void) { return _next; }
00063 private:
00064 Chunk * _myChunk;
00065 ChunkBlock * _next;
00066 };
00067
00068
00069 static inline ChunkBlock * getChunkBlock (void * ptr) {
00070 assert (ptr != NULL);
00071 return (ChunkBlock *) ptr - 1;
00072 }
00073
00074 private:
00075
00076 ChunkBlock * freeSlots;
00077 int numSlotsAvailable;
00078
00079 static inline size_t align (size_t sz) {
00080 return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
00081 }
00082
00083 };
00084
00085 template <int chunkSize, int slotSize>
00086 Chunk<chunkSize, slotSize>::Chunk (void)
00087 : freeSlots (NULL),
00088 numSlotsAvailable (getNumSlots())
00089 {
00090
00091 int numSlots = getNumSlots();
00092 assert (numSlots > 0);
00093 const int blksize = align(sizeof(ChunkBlock) + slotSize);
00094
00095
00096 ChunkBlock * b = (ChunkBlock *) (this + 1);
00097 for (int i = 0; i < numSlots; i++) {
00098 assert ((unsigned long) b < ((unsigned long) (this + 1) + blksize * numSlots));
00099 new (b) ChunkBlock;
00100 b->setChunk (this);
00101 assert (b->getChunk() == this);
00102 b->setNext (freeSlots);
00103 freeSlots = b;
00104 b = (ChunkBlock *) ((char *) b + blksize);
00105 }
00106 }
00107
00108
00109 template <int chunkSize, int slotSize>
00110 void * Chunk<chunkSize, slotSize>::getSlot (void)
00111 {
00112 if (freeSlots == NULL) {
00113 assert (numSlotsAvailable == 0);
00114 return NULL;
00115 }
00116 assert (numSlotsAvailable > 0);
00117 ChunkBlock * b = freeSlots;
00118 freeSlots = freeSlots->getNext();
00119 numSlotsAvailable--;
00120 b->setChunk (this);
00121 b->setNext (NULL);
00122 void * ptr = (void *) (b + 1);
00123 Chunk<chunkSize, slotSize> * bch = getChunk(ptr);
00124 assert (bch == this);
00125 return (void *) (b + 1);
00126 }
00127
00128
00129 template <int chunkSize, int slotSize>
00130 void Chunk<chunkSize, slotSize>::putSlot (void * ptr)
00131 {
00132 ChunkBlock * b = getChunkBlock (ptr);
00133 assert (b->getChunk() == this);
00134 b->setNext (freeSlots);
00135 freeSlots = b;
00136 numSlotsAvailable++;
00137 assert (numSlotsAvailable <= getNumSlots());
00138 }
00139
00140
00141 template <int chunkSize, int slotSize>
00142 int Chunk<chunkSize, slotSize>::getNumSlots (void)
00143 {
00144 return ((chunkSize - sizeof(Chunk)) / align (sizeof(ChunkBlock) + slotSize));
00145 }
00146
00147
00148 template <int chunkSize, int slotSize>
00149 int Chunk<chunkSize, slotSize>::getNumSlotsFree (void)
00150 {
00151 return numSlotsAvailable;
00152 }
00153
00154
00155 template <int chunkSize, int slotSize>
00156 int Chunk<chunkSize, slotSize>::getNumSlotsInUse (void)
00157 {
00158 return getNumSlots() - numSlotsAvailable;
00159 }
00160
00161
00162 template <int chunkSize, int slotSize>
00163 Chunk<chunkSize, slotSize> * Chunk<chunkSize, slotSize>::getChunk (void * ptr)
00164 {
00165 ChunkBlock * ch = getChunkBlock (ptr);
00166 return ch->getChunk();
00167 }
00168
00169 };
00170
00171 #endif