//========= Copyright Valve Corporation, All rights reserved. ============// // // The copyright to the contents herein is the property of Valve, L.L.C. // The contents may be used and/or copied only with the written permission of // Valve, L.L.C., or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // Purpose: // // $Workfile: $ // $Date: $ // //----------------------------------------------------------------------------- // $Log: $ // // $NoKeywords: $ //============================================================================= #ifndef TSMEMPOOL_H #define TSMEMPOOL_H #ifdef _WIN32 #pragma once #endif #undef new //----------------------------------------------------------------------------- // Purpose: Optimized pool memory allocator //----------------------------------------------------------------------------- class CThreadSafeMemoryPool { public: enum { GROW_NONE=0, // Don't allow new blobs. GROW_FAST=1, // New blob size is numElements * (i+1) (ie: the blocks it allocates get larger and larger each time it allocates one). GROW_SLOW=2, // New blob size is numElements. GROW_TIL_YOU_CANT=3 // GROW_SLOW til alloc fails - then STOP and dont assert! }; CThreadSafeMemoryPool( int blockSize, int numElements, int growMode = GROW_FAST ); ~CThreadSafeMemoryPool(); void *Alloc(); // Allocate the element size you specified in the constructor. void *Alloc( unsigned int cubAlloc ); void Free( void *pMem ); void Free( void *pMem, int cubAlloc ); // Frees everything void Clear(); // display void PrintStats(); size_t CubTotalSize(); size_t CubSizeInUse(); int Count(); static void * operator new( size_t size ) { CThreadSafeMemoryPool *pNode = (CThreadSafeMemoryPool *)MemAlloc_AllocAligned( size, 8, __FILE__, __LINE__ #ifdef STEAM , true // new operator #endif ); return pNode; } static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { CThreadSafeMemoryPool *pNode = (CThreadSafeMemoryPool *)MemAlloc_AllocAligned( size, 8, pFileName, nLine #ifdef STEAM , true // new operator #endif ); return pNode; } static void operator delete( void *p) { MemAlloc_FreeAligned( p #ifdef STEAM , true // new operator #endif ); } static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine ) { MemAlloc_FreeAligned( p #ifdef STEAM , true // new operator #endif ); } #ifdef DBGFLAG_VALIDATE void Validate( CValidator &validator, const char *pchName ); // Validate our internal structures #endif // DBGFLAG_VALIDATE private: // These ain't gonna work static void * operator new[] ( size_t size ); static void operator delete [] ( void *p); // CThreadSpinRWLock needs 8 byte alignment to work but we new() CThreadSafeMemoryPool // so simply place it at the start of the class to make sure it fits on the 8-byte boundary CThreadSpinRWLock m_threadRWLock; int m_nGrowMode; int m_cubBlockSize; int m_nGrowSize; void ClearNoLock(); CInterlockedInt m_cBlocksInUse; size_t m_cubAllocated; struct BlockSet_t { byte *m_pubBlockSet; size_t m_cubAllocated; }; CUtlVector m_vecBlockSets; class CTSListBase *m_ptslistFreeBlocks; }; //----------------------------------------------------------------------------- // Wrapper macro to make an allocator that returns particular typed allocations // and construction and destruction of objects. //----------------------------------------------------------------------------- template< class T > class CThreadSafeClassMemoryPool : public CThreadSafeMemoryPool { public: CThreadSafeClassMemoryPool(int numElements, int growMode = GROW_FAST) : CThreadSafeMemoryPool( sizeof(T), numElements, growMode ) {} T* Alloc(); void Free( T *pMem ); }; template< class T > T* CThreadSafeClassMemoryPool::Alloc() { T *pRet = (T*)CThreadSafeMemoryPool::Alloc(); if ( pRet ) { Construct( pRet ); } return pRet; } template< class T > void CThreadSafeClassMemoryPool::Free(T *pMem) { if ( pMem ) { Destruct( pMem ); } CThreadSafeMemoryPool::Free( pMem ); } #endif // TSMEMPOOL_H