Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 #ifndef _CHUNK_H_ 00004 #define _CHUNK_H_ 00005 00006 /* 00007 00008 Heap Layers: An Extensible Memory Allocation Infrastructure 00009 00010 Copyright (C) 2000-2003 by Emery Berger 00011 http://www.cs.umass.edu/~emery 00012 emery@cs.umass.edu 00013 00014 This program is free software; you can redistribute it and/or modify 00015 it under the terms of the GNU General Public License as published by 00016 the Free Software Foundation; either version 2 of the License, or 00017 (at your option) any later version. 00018 00019 This program is distributed in the hope that it will be useful, 00020 but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License 00025 along with this program; if not, write to the Free Software 00026 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 // Get and put slots. 00041 // Get returns NULL if there are no slots available. 00042 inline void * getSlot (void); 00043 inline void putSlot (void *); 00044 00045 // How many slots are there in total? 00046 inline static int getNumSlots (void); 00047 00048 // How many slots are available? 00049 inline int getNumSlotsFree (void); 00050 00051 // How many slots are available? 00052 inline int getNumSlotsInUse (void); 00053 00054 // Find a chunk given its slot. 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; // If allocated, point to the chunk. 00065 ChunkBlock * _next; // If not allocated, point to the next chunk block. 00066 }; 00067 00068 // Find a chunk block for a given pointer. 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 //printf ("numSlots = %d\n", numSlots); 00091 int numSlots = getNumSlots(); 00092 assert (numSlots > 0); 00093 const int blksize = align(sizeof(ChunkBlock) + slotSize); 00094 //printf ("blksize = %d\n", blksize); 00095 // Carve up the chunk into a number of slots. 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); // FIX ME -- this should be unnecessary. 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