//#include "precomp.h" #include "MemoryPool.h" #include /************************************************************************** **SA Network Connection Profiler [sancp] - A TCP/IP statistical/collection tool * ************************************************************************ * * Copyright (C) 2003 John Curry * * * * This program is distributed under the terms of version 1.0 of the * * Q Public License. See LICENSE.QPL for further details. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * * ***********************************************************************/ // // This code was derived directly from the contributions of: Noah Booth // Thanks Noah! // //////////////////////////////////////////////////////////////////////////////// // CBuffer //////////////////////////////////////////////////////////////////////////////// unsigned int min (unsigned int x,unsigned int y){ return (x>y)?y:x; } CBuffer::CBuffer(CMemoryPool* pPool) : m_pPool(pPool), m_dwSize(0), m_pNext(NULL), m_pPrev(NULL) { m_pBuffer = new BYTE[GetBufferSize()]; } CBuffer::~CBuffer() { if(m_pBuffer) delete[] m_pBuffer; } void CBuffer::Free() { m_pPool->Free(this); } BYTE* CBuffer::GetBuffer() { return m_pBuffer; } unsigned int CBuffer::GetBufferSize() { return m_pPool->GetBufferSize(); } unsigned int CBuffer::GetSizeUsed() { return m_dwSize; } unsigned int CBuffer::SetSizeUsed(unsigned int dwSizeUsed) { return m_dwSize = min(GetBufferSize(), dwSizeUsed); } //////////////////////////////////////////////////////////////////////////////// // CMemoryPool::CBufferCollection //////////////////////////////////////////////////////////////////////////////// CBufferCollection::CBufferCollection() : m_pHead(NULL), m_pTail(NULL), m_dwSize(0) { } CBufferCollection::~CBufferCollection() { Clear(); } void CBufferCollection::AddHead(CBuffer* pBuffer) { // The Tail for freePool was not messed up here 0 = prev<- tail ->next = 1. // How does anything become the tail? if(m_pHead == NULL) { m_pHead = m_pTail = pBuffer; pBuffer->m_pNext = pBuffer->m_pPrev = NULL; m_dwSize = 1; } else { pBuffer->m_pPrev = NULL; pBuffer->m_pNext = m_pHead; m_pHead->m_pPrev = pBuffer; m_pHead = pBuffer; m_dwSize++; } } CBuffer* CBufferCollection::RemoveTail() { CBuffer* pBuffer = NULL; if(m_pTail != NULL) { pBuffer = m_pTail; if(m_pTail->m_pPrev == NULL) { m_pHead = m_pTail = NULL; m_dwSize = 0; } else { m_pTail->m_pPrev->m_pNext = NULL; m_pTail = m_pTail->m_pPrev; pBuffer->m_pNext = pBuffer->m_pPrev = NULL; m_dwSize--; } } return pBuffer; } void CBufferCollection::Remove(CBuffer* pBuffer) { if(pBuffer != NULL) { m_dwSize--; if(pBuffer->m_pPrev == NULL) { m_pHead = pBuffer->m_pNext; } else { pBuffer->m_pPrev->m_pNext = pBuffer->m_pNext; } if(pBuffer->m_pNext == NULL) { m_pTail = pBuffer->m_pPrev; } else { pBuffer->m_pNext->m_pPrev = pBuffer->m_pPrev; pBuffer->m_pNext = NULL; } pBuffer->m_pPrev = NULL; } } CBuffer* CBufferCollection::Head() { return m_pHead; } CBuffer* CBufferCollection::Tail() { return m_pTail; } unsigned int CBufferCollection::Count() { return m_dwSize; } void CBufferCollection::Clear() { while(Count()) delete RemoveTail(); } //////////////////////////////////////////////////////////////////////////////// // CMemoryPool //////////////////////////////////////////////////////////////////////////////// CMemoryPool::CMemoryPool(bool bAutoGrow /*=false*/, unsigned int dwBufferSize /*=4096*/, unsigned int dwInitialCount /*=1024*/) : m_dwBufferSize(dwBufferSize), m_dwCount(dwInitialCount), m_bAutoGrow(bAutoGrow) { //InitializeCriticalSection(&m_critsec); Enter(); for(unsigned int dwBuffer = 0; dwBuffer < m_dwCount; dwBuffer++) { CBuffer* pNewBuffer = new CBuffer(this); m_freePool.AddHead(pNewBuffer); } Leave(); } CMemoryPool::~CMemoryPool() { //DeleteCriticalSection(&m_critsec); } CBuffer* CMemoryPool::Alloc() { CBuffer* pBuffer = NULL; unsigned int dwFreeCount; Enter(); dwFreeCount = m_freePool.Count(); if(m_bAutoGrow && dwFreeCount == 0) { Resize(m_dwCount * 2); dwFreeCount = m_freePool.Count(); } if(dwFreeCount > 0) { pBuffer = m_freePool.RemoveTail(); m_usedPool.AddHead(pBuffer); } Leave(); return pBuffer; } void CMemoryPool::Free(CBuffer* pBuffer) { Enter(); m_usedPool.Remove(pBuffer); m_freePool.AddHead(pBuffer); Leave(); } unsigned int CMemoryPool::GetTotalBuffers() { return m_dwCount; } unsigned int CMemoryPool::GetUsedBuffers() { return m_usedPool.Count(); } unsigned int CMemoryPool::GetFreeBuffers() { return m_freePool.Count(); } unsigned int CMemoryPool::GetBufferSize() { return m_dwBufferSize; } bool CMemoryPool::Resize(unsigned long dwNewCount) { bool bResult = true; Enter(); if(dwNewCount > m_dwCount) { while(m_dwCount < dwNewCount) { m_dwCount++; CBuffer* pNewBuffer = new CBuffer(this); m_freePool.AddHead(pNewBuffer); } } else { if(m_dwCount - dwNewCount > m_freePool.Count()) { bResult = false; } while(m_dwCount-- > dwNewCount) { delete m_freePool.RemoveTail(); } } Leave(); return bResult; } bool CMemoryPool::ResizeD(long iCountDiff) { return Resize(m_dwCount + iCountDiff); } bool CMemoryPool::IsAutoGrow() { return m_bAutoGrow; }