00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "pent_include.h"
00019
00020 #include "SegmentedPool.h"
00021
00022 DEFINE_RUNTIME_CLASSTYPE_CODE(SegmentedPool,Pool);
00023
00024
00025
00026
00027
00028
00029
00030
00031 #define OFFSET_ALIGN(X) ( (X + sizeof(uintptr) - 1) & ~(sizeof(uintptr) - 1) )
00032
00033 #ifdef USE_VALGRIND
00034 const int redzoneSize = 8;
00035 #else
00036 const int redzoneSize = 0;
00037 #endif
00038
00039 struct SegmentedPoolNode
00040 {
00041 SegmentedPool * pool;
00042 SegmentedPoolNode * nextFree;
00043 #ifdef USE_VALGRIND
00044 int valgrind_handle;
00045 #endif
00046 size_t size;
00047 };
00048
00049
00050
00051
00052 SegmentedPool::SegmentedPool(size_t nodeCapacity_, uint32 nodes_)
00053 : Pool(), nodes(nodes_), freeNodeCount(nodes_)
00054 {
00055 uint32 i;
00056
00057
00058
00059 nodeCapacity = OFFSET_ALIGN(nodeCapacity_ + redzoneSize);
00060 nodes = nodes_;
00061
00062
00063
00064 nodeOffset = OFFSET_ALIGN(sizeof(SegmentedPoolNode) + redzoneSize)
00065 + nodeCapacity;
00066
00067 startOfPool = new uint8[nodeOffset * nodes_];
00068 endOfPool = startOfPool + (nodeOffset * nodes_);
00069
00070 VALGRIND_CREATE_MEMPOOL(startOfPool, redzoneSize, 0);
00071
00072 firstFree = reinterpret_cast<SegmentedPoolNode*>(startOfPool);
00073 firstFree->pool = this;
00074 firstFree->size = 0;
00075
00076 lastFree = firstFree;
00077
00078 for (i = 1; i < nodes_; ++i)
00079 {
00080 lastFree->nextFree = reinterpret_cast<SegmentedPoolNode*>(startOfPool + i * nodeOffset);
00081 lastFree = lastFree->nextFree;
00082
00083 lastFree->pool = this;
00084 lastFree->size = 0;
00085 }
00086
00087 lastFree->nextFree = 0;
00088 }
00089
00090 SegmentedPool::~SegmentedPool()
00091 {
00092 assert(isEmpty());
00093
00094 VALGRIND_DESTROY_MEMPOOL(startOfPool);
00095
00096 delete [] startOfPool;
00097 }
00098
00099 void * SegmentedPool::allocate(size_t size)
00100 {
00101 SegmentedPoolNode* node;
00102
00103 if (isFull() || size > nodeCapacity)
00104 return 0;
00105
00106 --freeNodeCount;
00107 node = firstFree;
00108 node->size = size;
00109
00110 if (isFull())
00111 {
00112 firstFree = 0;
00113 lastFree = 0;
00114 }
00115 else
00116 {
00117 firstFree = firstFree->nextFree;
00118 }
00119
00120 node->nextFree = 0;
00121
00122
00123 uint8* p = reinterpret_cast<uint8 *>(node) +
00124 OFFSET_ALIGN(sizeof(SegmentedPoolNode) + redzoneSize);
00125
00126 VALGRIND_MEMPOOL_ALLOC(startOfPool, p, size);
00127 #ifdef USE_VALGRIND
00128 node->valgrind_handle = VALGRIND_CREATE_BLOCK(p, size,
00129 "SegmentedPoolBlock");
00130 #endif
00131
00132 return p;
00133 }
00134
00135 void SegmentedPool::deallocate(void * ptr)
00136 {
00137 SegmentedPoolNode* node;
00138
00139 if (inPool(ptr))
00140 {
00141 node = getPoolNode(ptr);
00142 node->size = 0;
00143 assert(node->pool == this);
00144
00145 VALGRIND_MEMPOOL_FREE(startOfPool, ptr);
00146 VALGRIND_DISCARD(node->valgrind_handle);
00147
00148
00149 if (isFull())
00150 {
00151 firstFree = node;
00152 lastFree = node;
00153 }
00154 else
00155 {
00156 lastFree->nextFree = node;
00157 lastFree = lastFree->nextFree;
00158 }
00159 ++freeNodeCount;
00160 }
00161 }
00162
00163 void SegmentedPool::printInfo()
00164 {
00165 uint16 i;
00166 size_t max, min, total;
00167 SegmentedPoolNode * node;
00168
00169 con.Printf(" start address 0x%X\tend address 0x%X\tnodeOffset 0x%X\n",
00170 startOfPool, endOfPool, nodeOffset);
00171 con.Printf(" nodeCapacity %d b\n total nodes %d\tfree nodes %d\n",
00172 nodeCapacity, nodes, freeNodeCount);
00173 con.Printf(" total memory: %d\tfree memory: %d\n",
00174 nodeCapacity * nodes, nodeCapacity * freeNodeCount);
00175
00176 max = 0;
00177 min = nodeCapacity;
00178 total = 0;
00179
00180 for (i = 0; i < nodes; ++i)
00181 {
00182 node = reinterpret_cast<SegmentedPoolNode*>(startOfPool + i * nodeOffset);
00183 if (node->size > 0)
00184 {
00185 max = node->size > max ? node->size : max;
00186 min = node->size < min ? node->size : min;
00187 total += node->size;
00188 }
00189 }
00190
00191 if (nodes > freeNodeCount)
00192 {
00193 con.Printf(" smallest node: %d b\tlargest node: %d b\taverage size: %d b\n",
00194 min, max, total / (nodes - freeNodeCount));
00195 }
00196 else
00197 {
00198 con.Printf(" Empty pool!!!\n");
00199 }
00200 }
00201
00202 SegmentedPoolNode* SegmentedPool::getPoolNode(void * ptr)
00203 {
00204 uint32 pos = (reinterpret_cast<uint8 *>(ptr) - startOfPool) / nodeOffset;
00205 return reinterpret_cast<SegmentedPoolNode*>(startOfPool + pos*nodeOffset);
00206 }
00207