Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 #ifndef _BIGCHUNK_H_ 00004 #define _BIGCHUNK_H_ 00005 00006 #include <assert.h> 00007 00008 template <int chunkSize, int slotSize, class Super> 00009 class BigChunk { 00010 public: 00011 00012 inline BigChunk (void); 00013 00014 // Get and put slots. 00015 // Get returns NULL if there are no slots available. 00016 inline void * getSlot (void); 00017 inline void putSlot (void *); 00018 00019 // How many slots are there in total? 00020 inline static int getNumSlots (void); 00021 00022 // How many slots are available? 00023 inline int getNumSlotsFree (void); 00024 00025 // How many slots are available? 00026 inline int getNumSlotsInUse (void); 00027 00028 // Find a chunk given its slot. 00029 inline static BigChunk * getChunk (void *); 00030 00031 class ChunkBlock { 00032 public: 00033 void setChunk (BigChunk * ch) { _myChunk = ch; } 00034 BigChunk * getChunk (void) { return _myChunk; } 00035 void setNext (ChunkBlock * n) { _next = n; } 00036 ChunkBlock * getNext (void) { return _next; } 00037 private: 00038 BigChunk * _myChunk; // If allocated, point to the chunk. 00039 ChunkBlock * _next; // If not allocated, point to the next chunk block. 00040 }; 00041 00042 // Find a chunk block for a given pointer. 00043 static inline ChunkBlock * getChunkBlock (void * ptr) { 00044 assert (ptr != NULL); 00045 return (ChunkBlock *) ptr - 1; 00046 } 00047 00048 void setHeap (Super * h) { 00049 heap = h; 00050 } 00051 00052 inline Super * getHeap (void) { 00053 return heap; 00054 } 00055 00056 // Add doubly linked-list operations. 00057 inline BigChunk * getNext (void); 00058 inline BigChunk * getPrev (void); 00059 inline void setNext (BigChunk *); 00060 inline void setPrev (BigChunk *); 00061 00062 private: 00063 00064 static inline size_t align (size_t sz) { 00065 return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1); 00066 } 00067 00068 ChunkBlock * freeSlots; 00069 int numSlotsAvailable; 00070 Super * heap; 00071 BigChunk * prev; 00072 BigChunk * next; 00073 }; 00074 00075 00076 template <int chunkSize, int slotSize, class Super> 00077 BigChunk<chunkSize, slotSize, Super> * BigChunk<chunkSize, slotSize, Super>::getNext (void) 00078 { 00079 return next; 00080 } 00081 00082 00083 template <int chunkSize, int slotSize, class Super> 00084 BigChunk<chunkSize, slotSize, Super> * BigChunk<chunkSize, slotSize, Super>::getPrev (void) 00085 { 00086 return prev; 00087 } 00088 00089 00090 template <int chunkSize, int slotSize, class Super> 00091 void BigChunk<chunkSize, slotSize, Super>::setNext (BigChunk<chunkSize, slotSize, Super> * ptr) 00092 { 00093 next = ptr; 00094 } 00095 00096 00097 template <int chunkSize, int slotSize, class Super> 00098 void BigChunk<chunkSize, slotSize, Super>::setPrev (BigChunk<chunkSize, slotSize, Super> * ptr) 00099 { 00100 prev = ptr; 00101 } 00102 00103 00104 template <int chunkSize, int slotSize, class Super> 00105 BigChunk<chunkSize, slotSize, Super>::BigChunk (void) 00106 : freeSlots (NULL), 00107 numSlotsAvailable (getNumSlots()), 00108 prev (NULL), 00109 next (NULL) 00110 { 00111 //printf ("numSlots = %d\n", numSlots); 00112 int numSlots = getNumSlots(); 00113 assert (numSlots > 0); 00114 const int blksize = align(sizeof(ChunkBlock) + slotSize); 00115 //printf ("blksize = %d\n", blksize); 00116 // Carve up the chunk into a number of slots. 00117 ChunkBlock * b = (ChunkBlock *) (this + 1); 00118 for (int i = 0; i < numSlots; i++) { 00119 assert ((unsigned long) b < ((unsigned long) (this + 1) + blksize * numSlots)); 00120 new (b) ChunkBlock; 00121 b->setChunk (this); 00122 assert (b->getChunk() == this); 00123 b->setNext (freeSlots); 00124 freeSlots = b; 00125 b = (ChunkBlock *) ((char *) b + blksize); 00126 } 00127 } 00128 00129 00130 template <int chunkSize, int slotSize, class Super> 00131 void * BigChunk<chunkSize, slotSize, Super>::getSlot (void) 00132 { 00133 if (freeSlots == NULL) { 00134 assert (numSlotsAvailable == 0); 00135 return NULL; 00136 } 00137 assert (numSlotsAvailable > 0); 00138 assert (numSlotsAvailable <= getNumSlots()); 00139 ChunkBlock * b = freeSlots; 00140 freeSlots = freeSlots->getNext(); 00141 numSlotsAvailable--; 00142 b->setChunk (this); // FIX ME -- this should be unnecessary. 00143 b->setNext (NULL); 00144 void * ptr = (void *) (b + 1); 00145 BigChunk<chunkSize, slotSize, Super> * bch = getChunk(ptr); 00146 assert (bch == this); 00147 return (void *) (b + 1); 00148 } 00149 00150 00151 template <int chunkSize, int slotSize, class Super> 00152 void BigChunk<chunkSize, slotSize, Super>::putSlot (void * ptr) 00153 { 00154 assert (numSlotsAvailable >= 0); 00155 assert (numSlotsAvailable <= getNumSlots()); 00156 ChunkBlock * b = getChunkBlock (ptr); 00157 assert (b->getChunk() == this); 00158 b->setNext (freeSlots); 00159 freeSlots = b; 00160 numSlotsAvailable++; 00161 assert (numSlotsAvailable > 0); 00162 assert (numSlotsAvailable <= getNumSlots()); 00163 } 00164 00165 00166 template <int chunkSize, int slotSize, class Super> 00167 int BigChunk<chunkSize, slotSize, Super>::getNumSlots (void) 00168 { 00169 return ((chunkSize - sizeof(BigChunk)) / align (sizeof(ChunkBlock) + slotSize)); 00170 } 00171 00172 00173 template <int chunkSize, int slotSize, class Super> 00174 int BigChunk<chunkSize, slotSize, Super>::getNumSlotsFree (void) 00175 { 00176 return numSlotsAvailable; 00177 } 00178 00179 00180 template <int chunkSize, int slotSize, class Super> 00181 int BigChunk<chunkSize, slotSize, Super>::getNumSlotsInUse (void) 00182 { 00183 return getNumSlots() - numSlotsAvailable; 00184 } 00185 00186 00187 template <int chunkSize, int slotSize, class Super> 00188 BigChunk<chunkSize, slotSize, Super> * BigChunk<chunkSize, slotSize, Super>::getChunk (void * ptr) 00189 { 00190 ChunkBlock * ch = getChunkBlock (ptr); 00191 return ch->getChunk(); 00192 } 00193 00194 #endif