diff options
Diffstat (limited to 'external/vpc/public/tier1/memstack.h')
| -rw-r--r-- | external/vpc/public/tier1/memstack.h | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/external/vpc/public/tier1/memstack.h b/external/vpc/public/tier1/memstack.h new file mode 100644 index 0000000..f1846d2 --- /dev/null +++ b/external/vpc/public/tier1/memstack.h @@ -0,0 +1,348 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: A fast stack memory allocator that uses virtual memory if available +// +//===========================================================================// + +#ifndef MEMSTACK_H +#define MEMSTACK_H + +#if defined( _WIN32 ) +#pragma once +#endif + +#include "tier1/utlvector.h" + +#if defined( _WIN32 ) || defined( _PS3 ) +#define MEMSTACK_VIRTUAL_MEMORY_AVAILABLE +#endif + +//----------------------------------------------------------------------------- + +typedef unsigned MemoryStackMark_t; + +class CMemoryStack +{ +public: + CMemoryStack(); + ~CMemoryStack(); + + bool Init( const char *pszAllocOwner, unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 ); +#ifdef _GAMECONSOLE + bool InitPhysical( const char *pszAllocOwner, uint size, uint nBaseAddrAlignment, uint alignment = 16, uint32 nAdditionalFlags = 0 ); +#endif + void Term(); + + int GetSize(); + int GetMaxSize(); + int GetUsed(); + + void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT; + + MemoryStackMark_t GetCurrentAllocPoint(); + void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true ); + void FreeAll( bool bDecommit = true ); + + void Access( void **ppRegion, unsigned *pBytes ); + + void PrintContents(); + + void *GetBase(); + const void *GetBase() const { return const_cast<CMemoryStack *>(this)->GetBase(); } + + bool CommitSize( int ); + + void SetAllocOwner( const char *pszAllocOwner ); + +private: + bool CommitTo( byte * ) RESTRICT; + void RegisterAllocation(); + void RegisterDeallocation( bool bShouldSpew ); + + byte *m_pNextAlloc; + byte *m_pCommitLimit; + byte *m_pAllocLimit; + + byte *m_pBase; + bool m_bRegisteredAllocation; + bool m_bPhysical; + char *m_pszAllocOwner; + + unsigned m_maxSize; + unsigned m_alignment; +#ifdef MEMSTACK_VIRTUAL_MEMORY_AVAILABLE + unsigned m_commitSize; + unsigned m_minCommit; +#endif +#if defined( MEMSTACK_VIRTUAL_MEMORY_AVAILABLE ) && defined( _PS3 ) + IVirtualMemorySection *m_pVirtualMemorySection; +#endif +}; + +//------------------------------------- + +FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT +{ + Assert( m_pBase ); + + bytes = MAX( bytes, m_alignment ); + bytes = AlignValue( bytes, m_alignment ); + + void *pResult = m_pNextAlloc; + byte *pNextAlloc = m_pNextAlloc + bytes; + + if ( pNextAlloc > m_pCommitLimit ) + { + if ( !CommitTo( pNextAlloc ) ) + { + return NULL; + } + } + + if ( bClear ) + { + memset( pResult, 0, bytes ); + } + + m_pNextAlloc = pNextAlloc; + + return pResult; +} + +//------------------------------------- + +inline bool CMemoryStack::CommitSize( int nBytes ) +{ + if ( GetSize() != nBytes ) + { + return CommitTo( m_pBase + nBytes ); + } + return true; +} + +//------------------------------------- + +inline int CMemoryStack::GetMaxSize() +{ + return m_maxSize; +} + +//------------------------------------- + +inline int CMemoryStack::GetUsed() +{ + return ( m_pNextAlloc - m_pBase ); +} + +//------------------------------------- + +inline void *CMemoryStack::GetBase() +{ + return m_pBase; +} + +//------------------------------------- + +inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint() +{ + return ( m_pNextAlloc - m_pBase ); +} + + +//----------------------------------------------------------------------------- +// The CUtlMemoryStack class: +// A fixed memory class +//----------------------------------------------------------------------------- +template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 > +class CUtlMemoryStack +{ +public: + // constructor, destructor + CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( "CUtlMemoryStack", MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); } + CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); } + + // Can we use this index? + bool IsIdxValid( I i ) const { long x=i; return (x >= 0) && (x < m_nAllocated); } + + // Specify the invalid ('null') index that we'll only return on failure + static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT + static I InvalidIndex() { return INVALID_INDEX; } + + class Iterator_t + { + Iterator_t( I i ) : index( i ) {} + I index; + friend class CUtlMemoryStack<T,I,MAX_SIZE, COMMIT_SIZE, INITIAL_COMMIT>; + public: + bool operator==( const Iterator_t it ) const { return index == it.index; } + bool operator!=( const Iterator_t it ) const { return index != it.index; } + }; + Iterator_t First() const { return Iterator_t( m_nAllocated ? 0 : InvalidIndex() ); } + Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? it.index + 1 : InvalidIndex() ); } + I GetIndex( const Iterator_t &it ) const { return it.index; } + bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; } + bool IsValidIterator( const Iterator_t &it ) const { long x=it.index; return x >= 0 && x < m_nAllocated; } + Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } + + // Gets the base address + T* Base() { return (T*)m_MemoryStack.GetBase(); } + const T* Base() const { return (const T*)m_MemoryStack.GetBase(); } + + // element access + T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; } + const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } + T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; } + const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } + + // Attaches the buffer to external memory.... + void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } + + // Size + int NumAllocated() const { return m_nAllocated; } + int Count() const { return m_nAllocated; } + + // Grows the memory, so that at least allocated + num elements are allocated + void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); } + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); } + + // Memory deallocation + void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; } + + // is the memory externally allocated? + bool IsExternallyAllocated() const { return false; } + + // Set the size by which the memory grows + void SetGrowSize( int size ) { Assert( 0 ); } + + // Identify the owner of this memory stack's memory + void SetAllocOwner( const char *pszAllocOwner ) { m_MemoryStack.SetAllocOwner( pszAllocOwner ); } + +private: + CMemoryStack m_MemoryStack; + int m_nAllocated; +}; + + +#ifdef _X360 +//----------------------------------------------------------------------------- +// A memory stack used for allocating physical memory on the 360 +// Usage pattern anticipates we usually never go over the initial allocation +// When we do so, we're ok with slightly slower allocation +//----------------------------------------------------------------------------- +class CPhysicalMemoryStack +{ +public: + CPhysicalMemoryStack(); + ~CPhysicalMemoryStack(); + + // The physical memory stack is allocated in chunks. We will initially + // allocate nInitChunkCount chunks, which will always be in memory. + // When FreeAll() is called, it will free down to the initial chunk count + // but not below it. + bool Init( size_t nChunkSizeInBytes, size_t nAlignment, int nInitialChunkCount, uint32 nAdditionalFlags ); + void Term(); + + size_t GetSize() const; + size_t GetPeakUsed() const; + size_t GetUsed() const; + size_t GetFramePeakUsed() const; + + MemoryStackMark_t GetCurrentAllocPoint() const; + void FreeToAllocPoint( MemoryStackMark_t mark, bool bUnused = true ); // bUnused is for interface compat with CMemoryStack + void *Alloc( size_t nSizeInBytes, bool bClear = false ) RESTRICT; + void FreeAll( bool bUnused = true ); // bUnused is for interface compat with CMemoryStack + + void PrintContents(); + +private: + void *AllocFromOverflow( size_t nSizeInBytes ); + + struct PhysicalChunk_t + { + uint8 *m_pBase; + uint8 *m_pNextAlloc; + uint8 *m_pAllocLimit; + }; + + PhysicalChunk_t m_InitialChunk; + CUtlVector< PhysicalChunk_t > m_ExtraChunks; + size_t m_nUsage; + size_t m_nFramePeakUsage; + size_t m_nPeakUsage; + size_t m_nAlignment; + size_t m_nChunkSizeInBytes; + int m_nFirstAvailableChunk; + int m_nAdditionalFlags; + PhysicalChunk_t *m_pLastAllocedChunk; +}; + +//------------------------------------- + +FORCEINLINE void *CPhysicalMemoryStack::Alloc( size_t nSizeInBytes, bool bClear ) RESTRICT +{ + if ( nSizeInBytes ) + { + nSizeInBytes = AlignValue( nSizeInBytes, m_nAlignment ); + } + else + { + nSizeInBytes = m_nAlignment; + } + + // Can't do an allocation bigger than the chunk size + Assert( nSizeInBytes <= m_nChunkSizeInBytes ); + + void *pResult = m_InitialChunk.m_pNextAlloc; + uint8 *pNextAlloc = m_InitialChunk.m_pNextAlloc + nSizeInBytes; + if ( pNextAlloc <= m_InitialChunk.m_pAllocLimit ) + { + m_InitialChunk.m_pNextAlloc = pNextAlloc; + m_pLastAllocedChunk = &m_InitialChunk; + } + else + { + pResult = AllocFromOverflow( nSizeInBytes ); + } + + m_nUsage += nSizeInBytes; + m_nFramePeakUsage = MAX( m_nUsage, m_nFramePeakUsage ); + m_nPeakUsage = MAX( m_nUsage, m_nPeakUsage ); + + if ( bClear ) + { + memset( pResult, 0, nSizeInBytes ); + } + + return pResult; +} + +//------------------------------------- + +inline size_t CPhysicalMemoryStack::GetPeakUsed() const +{ + return m_nPeakUsage; +} + +//------------------------------------- + +inline size_t CPhysicalMemoryStack::GetUsed() const +{ + return m_nUsage; +} + +inline size_t CPhysicalMemoryStack::GetFramePeakUsed() const +{ + return m_nFramePeakUsage; +} + +inline MemoryStackMark_t CPhysicalMemoryStack::GetCurrentAllocPoint() const +{ + Assert( m_pLastAllocedChunk ); + return ( m_pLastAllocedChunk->m_pNextAlloc - m_pLastAllocedChunk->m_pBase ); +} + +#endif // _X360 + +#endif // MEMSTACK_H |