#pragma once #include class C4JMemoryPool { public: unsigned int Align(unsigned int val, unsigned int align) { return int((val+(align-1))/align) * align; } virtual void* Alloc(size_t size) = 0; virtual void Free(void* ptr) = 0; }; // Fast Efficient Fixed-Size Memory Pool : No Loops and No Overhead // http://www.alogicalmind.com/memory_pools/index.htm class C4JMemoryPoolFixed : public C4JMemoryPool { // Basic type define typedef unsigned int uint; typedef unsigned char uchar; uint m_numOfBlocks; // Num of blocks uint m_sizeOfEachBlock; // Size of each block uint m_numFreeBlocks; // Num of remaining blocks uint m_numInitialized; // Num of initialized blocks uchar* m_memStart; // Beginning of memory pool uchar* m_memEnd; // End of memory pool uchar* m_next; // Num of next free block // CRITICAL_SECTION m_CS; public: C4JMemoryPoolFixed() { m_numOfBlocks = 0; m_sizeOfEachBlock = 0; m_numFreeBlocks = 0; m_numInitialized = 0; m_memStart = NULL; m_memEnd = NULL; m_next = 0; } C4JMemoryPoolFixed(uint sizeOfEachBlock, uint numOfBlocks) { CreatePool(sizeOfEachBlock, numOfBlocks); } ~C4JMemoryPoolFixed() { DestroyPool(); } void CreatePool(uint sizeOfEachBlock, uint numOfBlocks) { assert(sizeOfEachBlock >= 4); // has to be at least the size of an int, for book keeping m_numOfBlocks = numOfBlocks; m_sizeOfEachBlock = sizeOfEachBlock; m_numFreeBlocks = numOfBlocks; m_numInitialized = 0; m_memStart = new uchar[ m_sizeOfEachBlock * m_numOfBlocks ]; m_memEnd = m_memStart + (m_sizeOfEachBlock * m_numOfBlocks); m_next = m_memStart; // InitializeCriticalSection(&m_CS); } void DestroyPool() { delete[] m_memStart; m_memStart = NULL; } uchar* AddrFromIndex(uint i) const { return m_memStart + ( i * m_sizeOfEachBlock ); } uint IndexFromAddr(const uchar* p) const { return (((uint)(p - m_memStart)) / m_sizeOfEachBlock); } virtual void* Alloc(size_t size) { if(size > m_sizeOfEachBlock) return ::malloc(size); // EnterCriticalSection(&m_CS); if (m_numInitialized < m_numOfBlocks ) { uint* p = (uint*)AddrFromIndex( m_numInitialized ); *p = m_numInitialized + 1; m_numInitialized++; } void* ret = NULL; if ( m_numFreeBlocks > 0 ) { ret = (void*)m_next; --m_numFreeBlocks; if (m_numFreeBlocks!=0) { m_next = AddrFromIndex( *((uint*)m_next) ); } else { m_next = NULL; } } // LeaveCriticalSection(&m_CS); return ret; } virtual void Free(void* ptr) { if(ptr < m_memStart || ptr > m_memEnd) { ::free(ptr); return; } // EnterCriticalSection(&m_CS); if (m_next != NULL) { (*(uint*)ptr) = IndexFromAddr( m_next ); m_next = (uchar*)ptr; } else { *((uint*)ptr) = m_numOfBlocks; m_next = (uchar*)ptr; } ++m_numFreeBlocks; // LeaveCriticalSection(&m_CS); } }; // End pool class // this pool will constantly grow until it is reset (automatically when all allocs have been "freed") class C4JMemoryPoolGrow : public C4JMemoryPool { uint32_t m_totalSize; uint32_t m_memUsed; uint32_t m_numAllocations; uint8_t* m_pMemory; uint32_t m_currentOffset; public: C4JMemoryPoolGrow(uint32_t size = 64*1024) { size = Align(size, 4); m_totalSize = size; m_pMemory = new uint8_t[size]; m_currentOffset = 0; m_memUsed = 0; m_numAllocations = 0; } virtual void* Alloc(size_t size) { size = Align(size, 4); // 4 byte align the memory assert((m_currentOffset + size) < m_totalSize); // make sure we haven't ran out of space void* returnMem = &m_pMemory[m_currentOffset]; // grab the return memory m_currentOffset += size; m_numAllocations++; return returnMem; } virtual void Free(void* ptr) { m_numAllocations--; if(m_numAllocations == 0) m_currentOffset = 0; // reset the pool when we reach zero allocations } };