/////////////////////////////////////////////////////////////////////////// // // Copyright(C) 1997-1998 Microsoft Corporation all rights reserved. // // Module: iascompool.h // // Project: Everest // // Description: Object pool that uses CoTaskMemAlloc() / CoTaskMemFree() // // Author: TLP 11/11/97 // /////////////////////////////////////////////////////////////////////////// #ifndef __IAS_COM_MEMPOOL_H_ #define __IAS_COM_MEMPOOL_H_ // Assume another include has #included ias.h #include #include using namespace std; #define COM_MEMPOOL_INITIALIZED 1 #define COM_MEMPOOL_UNINITIALIZED 0 // // NOTE: m_lState must be aligned on 32 bit value or calls to // InterlockedExchange will fail on multi-processor x86 systems. template < class T, DWORD dwPerAllocT, bool bFixedSize > class CComMemPool { // State flag - 1 = mem pool initialized, 0 = mem pool uninitialized LONG m_lState; // Total number of items allocated DWORD m_dwCountTotal; // Number of items on the free list DWORD m_dwCountFree; // Highest number of outstanding allocations DWORD m_dwHighWater; // Number of objects per system memory allocation DWORD m_dwPerAllocT; // Fixed size pool flag bool m_bFixedSize; // Critical Section - serializes free item list access CRITICAL_SECTION m_CritSec; // Memory block list typedef list MemBlockList; typedef MemBlockList::iterator MemBlockListIterator; MemBlockList m_listMemBlocks; // Free item list typedef list FreeList; typedef FreeList::iterator FreeListIterator; FreeList m_listFreeT; // Disallow copy and assignment CComMemPool(const CComMemPool& theClass); CComMemPool& operator=(const CComMemPool& theClass); public: // // Constructor // CComMemPool() : m_listMemBlocks(0), m_listFreeT(0) // pre-alloc space for list nodes { m_lState = COM_MEMPOOL_UNINITIALIZED; m_dwPerAllocT = dwPerAllocT; m_bFixedSize = bFixedSize; m_dwCountTotal = 0; m_dwCountFree = 0; m_dwHighWater = 0; InitializeCriticalSection(&m_CritSec); } // // Destructor // ~CComMemPool() { _ASSERT( COM_MEMPOOL_UNINITIALIZED == m_lState ); DeleteCriticalSection(&m_CritSec); } ////////////////////////////////////////////////////////////////////////// // Init() - Initialize the memory pool ////////////////////////////////////////////////////////////////////////// bool Init(void) { bool bReturn = false; if ( COM_MEMPOOL_UNINITIALIZED == InterlockedExchange(&m_lState, COM_MEMPOOL_INITIALIZED) ) { if ( AllocateMemBlock() ) { bReturn = true; } else { InterlockedExchange(&m_lState, COM_MEMPOOL_UNINITIALIZED); } } else { _ASSERTE(FALSE); } return bReturn; } ////////////////////////////////////////////////////////////////////////// // Shutdown() - Shutdown the memory pool freeing any system resources used ////////////////////////////////////////////////////////////////////////// void Shutdown(void) { MemBlockListIterator p; MemBlockListIterator q; if ( COM_MEMPOOL_INITIALIZED == InterlockedExchange(&m_lState, COM_MEMPOOL_UNINITIALIZED) ) { if ( m_dwCountTotal != m_dwCountFree ) { // Still have blocks outstanding... // _ASSERTE( FALSE ); } if ( ! m_listMemBlocks.empty() ) { p = m_listMemBlocks.begin(); q = m_listMemBlocks.end(); while ( p != q ) { CoTaskMemFree(*p); p++; } m_listMemBlocks.clear(); } m_dwCountTotal = 0; m_dwCountFree = 0; } else { // COM pool is not inititalized // _ASSERTE( FALSE ); } } ////////////////////////////////////////////////////////////////////////// // Alloc() - Allocate an unitialized object from the pool ////////////////////////////////////////////////////////////////////////// T* Alloc(void) { T* pMemBlk = NULL; TraceFunctEnter("CComMemPool::Alloc()"); if ( COM_MEMPOOL_INITIALIZED == m_lState ) { EnterCriticalSection(&m_CritSec); if ( m_listFreeT.empty() ) { if ( ! m_bFixedSize ) { if ( AllocateMemBlock() ) { pMemBlk = m_listFreeT.front(); m_listFreeT.pop_front(); m_dwCountFree--; if ( m_dwHighWater < (m_dwCountTotal - m_dwCountFree) ) { m_dwHighWater++; } } else { ErrorTrace(0,"Could not allocate memory!"); } } else { ErrorTrace(0,"Fixed size pool is exhausted!"); } } else { pMemBlk = m_listFreeT.front(); m_listFreeT.pop_front(); m_dwCountFree--; if ( m_dwHighWater < (m_dwCountTotal - m_dwCountFree) ) { m_dwHighWater++; } } LeaveCriticalSection(&m_CritSec); } else { ErrorTrace(0,"The memory pool is not initialized!"); _ASSERTE( FALSE ); } if ( pMemBlk ) { memset(pMemBlk, 0, sizeof(T)); new (pMemBlk) T(); // Placement new for class T - requires default contructor } TraceFunctLeave(); return pMemBlk; } ////////////////////////////////////////////////////////////////////////// // Free() - Return an object to the memory pool ////////////////////////////////////////////////////////////////////////// void Free(T *pMemBlk) { TraceFunctEnter("CComMemPool::Free()"); if ( COM_MEMPOOL_INITIALIZED == m_lState ) { pMemBlk->~T(); // Explicit call to destructor due to placement new EnterCriticalSection(&m_CritSec); m_listFreeT.insert(m_listFreeT.begin(),pMemBlk); m_dwCountFree++; LeaveCriticalSection(&m_CritSec); } else { ErrorTrace(0,"The memory pool is not initialized!"); _ASSERTE( FALSE ); } TraceFunctLeave(); } ////////////////////////////////////////////////////////////////////////// // Dump() - Dump the contents of the memory pool - Debug Service ////////////////////////////////////////////////////////////////////////// void Dump(void) { #ifdef DEBUG UINT i; MemBlockListIterator p; FreeListIterator r; FreeListIterator s; TraceFunctEnter("CComMemPool::Dump()"); if ( COM_MEMPOOL_INITIALIZED == m_lState ) { // Dump the counts EnterCriticalSection(&m_CritSec); DebugTrace(0,"m_dwCountTotal = %d", m_dwCountTotal); DebugTrace(0,"m_dwCountFree = %d", m_dwCountFree); DebugTrace(0,"m_dwHighWater = %d", m_dwHighWater); // Dump the pointers to memory blocks DebugTrace(0,"m_listMemBlocks.size() = %d", m_listMemBlocks.size()); p = m_listMemBlocks.begin(); i = 0; while ( p != m_listMemBlocks.end() ) { DebugTrace(0,"m_listMemBlocks block %d = $%p", i, *p); i++; p++; } // Dump the pointers to items DebugTrace(0,"CComMemPool::Dump() - m_listFreeT.size() = %d", m_listFreeT.size()); r = m_listFreeT.begin(); i = 0; while ( r != m_listFreeT.end() ) { DebugTrace(0,"CComMemPool::Dump() - m_listFreeT item %d = $%p", i, *r); i++; r++; } LeaveCriticalSection(&m_CritSec); } else { ErrorTrace(0,"The memory pool is not initialized!"); _ASSERTE( FALSE ); } TraceFunctLeave(); #endif // DEBUG } private: ////////////////////////////////////////////////////////////////////////// // AllocateMemBlock() - Allocate some system memory and chop it into // T sized blocks ////////////////////////////////////////////////////////////////////////// bool AllocateMemBlock() { bool bReturn = false; UINT i; UINT uBlkSize; T* lpMemBlock; TraceFunctEnter("CComMemPool::AllocateMemBlock()"); uBlkSize = m_dwPerAllocT * sizeof(T); lpMemBlock = (T*) CoTaskMemAlloc(uBlkSize); if ( lpMemBlock ) { memset(lpMemBlock, 0, uBlkSize); m_listMemBlocks.insert(m_listMemBlocks.begin(), (PVOID)lpMemBlock); // Chop up the newly allocated memory block into sizeof(T) sized elements and place // the elements on the list of pointers to Ts. for ( i = 0; i < m_dwPerAllocT; i++ ) { m_listFreeT.insert(m_listFreeT.end(),lpMemBlock); lpMemBlock++; } // Update the pool memory use variables m_dwCountTotal += m_dwPerAllocT; m_dwCountFree += m_dwPerAllocT; bReturn = true; } TraceFunctLeave(); return bReturn; } }; // End of CComMemPool #endif // __IAS_COM_MEMPOOL_H_