//MemoryPool.cpp //Lee Noll #include "MemoryPool.h" #include #ifdef _WIN32 #include #include #else #include #define _ASSERTE(b) #endif void *CMemoryPool::m_pTempThis; CMemoryPool *CMemoryPool::m_pTempParent; void * CMemoryPool::m_pTempFree; size_t CMemoryPool::m_nTempCount; CMemoryPool *CMemoryPool::MostRemovedAncestor(CMemoryPool *pParent) { while (pParent->m_pParent) pParent = pParent->m_pParent; return pParent; } size_t CMemoryPool::Align(size_t stAllocateBlock) { const size_t AlignTo = 16; size_t actual = (stAllocateBlock/AlignTo)*AlignTo; if (actual < stAllocateBlock) actual += AlignTo; return actual; } void * CMemoryPool::Alloc(size_t stAllocateBlock, CMemoryPool *pParent) { void *pThis = NULL; pParent = MostRemovedAncestor(pParent); stAllocateBlock = Align(stAllocateBlock); if (pParent->m_nCount > stAllocateBlock) { pThis = pParent->m_pFree; pParent->m_pFree = (char *)pThis + stAllocateBlock; pParent->m_nCount -= stAllocateBlock; } return pThis; } void * CMemoryPool::Alloc(size_t stAllocateBlock) { return Alloc(stAllocateBlock, m_pParent); } //Absolutely the first construction after using either of the new operators! CMemoryPool::CMemoryPool() { //sanity check _ASSERTE((void *)this == m_pTempThis); m_pParent = m_pTempParent; m_pFree = m_pTempFree; m_nCount = m_nTempCount; } CMemoryPool::~CMemoryPool() { m_pTempParent = m_pParent; m_pTempThis = this; } //establish the Memory Pool for all subsequent allocations //these hide the global operator new //implicit static member function void * CMemoryPool::operator new (size_t stAllocateBlock, size_t total) { m_pTempThis = NULL; m_pTempParent = NULL; m_pTempFree = NULL; m_nTempCount = 0; stAllocateBlock = Align(stAllocateBlock); total = Align(total); if (total >= stAllocateBlock) m_pTempThis = malloc(total); if (m_pTempThis != NULL) { m_pTempFree = (char *)m_pTempThis + stAllocateBlock; m_nTempCount = total - stAllocateBlock; } return m_pTempThis; } //allocate from the most removed ancestor's pool //implicit static member function void * CMemoryPool::operator new (size_t stAllocateBlock, CMemoryPool *pParent) { m_pTempThis = NULL; m_pTempParent = pParent; m_pTempFree = NULL; m_nTempCount = 0; m_pTempThis = Alloc(stAllocateBlock, pParent); return m_pTempThis; } //doesn't do anything to reverse the second new, only the first one //this hides the global operator delete //implicit static member function void CMemoryPool::operator delete (void *pvMem) { //sanity check _ASSERTE(pvMem == m_pTempThis); if (m_pTempParent == NULL) free(pvMem); } void CMemoryPool::operator delete (void *pvMem, size_t total) { //sanity check _ASSERTE(pvMem == m_pTempThis); free(pvMem); } void CMemoryPool::operator delete (void *pvMem, CMemoryPool *pParent) { } //test #if 0 class CJunk : public CMemoryPool { private: int junk; public: CJunk() {} }; void test() { CJunk *p, *j; p = new (8192) CJunk(); j = new (p) CJunk(); delete j; delete p; } #endif