diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /external/vpc/public/tier1/utlfixedmemory.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'external/vpc/public/tier1/utlfixedmemory.h')
| -rw-r--r-- | external/vpc/public/tier1/utlfixedmemory.h | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/external/vpc/public/tier1/utlfixedmemory.h b/external/vpc/public/tier1/utlfixedmemory.h new file mode 100644 index 0000000..a124889 --- /dev/null +++ b/external/vpc/public/tier1/utlfixedmemory.h @@ -0,0 +1,354 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +// +// A growable memory class. +//===========================================================================// + +#ifndef UTLFIXEDMEMORY_H +#define UTLFIXEDMEMORY_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/dbg.h" +#include "tier0/platform.h" + +#include "tier0/memalloc.h" +#include "tier0/memdbgon.h" + +#pragma warning (disable:4100) +#pragma warning (disable:4514) + +//----------------------------------------------------------------------------- + +#ifdef UTLFIXEDMEMORY_TRACK +#define UTLFIXEDMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) +#define UTLFIXEDMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "||Sum of all UtlFixedMemory||", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) +#else +#define UTLFIXEDMEMORY_TRACK_ALLOC() ((void)0) +#define UTLFIXEDMEMORY_TRACK_FREE() ((void)0) +#endif + + +//----------------------------------------------------------------------------- +// The CUtlFixedMemory class: +// A growable memory class that allocates non-sequential blocks, but is indexed sequentially +//----------------------------------------------------------------------------- +template< class T > +class CUtlFixedMemory +{ +public: + // constructor, destructor + CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 ); + ~CUtlFixedMemory(); + + // Set the size by which the memory grows + void Init( int nGrowSize = 0, int nInitSize = 0 ); + + // here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL + T* Base() { return NULL; } + const T* Base() const { return NULL; } + +protected: + struct BlockHeader_t; + +public: + class Iterator_t + { + public: + Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {} + BlockHeader_t *m_pBlockHeader; + int m_nIndex; + + bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; } + bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; } + }; + Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); } + Iterator_t Next( const Iterator_t &it ) const + { + Assert( IsValidIterator( it ) ); + if ( !IsValidIterator( it ) ) + return InvalidIterator(); + + BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader; + if ( it.m_nIndex + 1 < pHeader->m_nBlockSize ) + return Iterator_t( pHeader, it.m_nIndex + 1 ); + + return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator(); + } + int GetIndex( const Iterator_t &it ) const + { + Assert( IsValidIterator( it ) ); + if ( !IsValidIterator( it ) ) + return InvalidIndex(); + + return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex ); + } + bool IsIdxAfter( int i, const Iterator_t &it ) const + { + Assert( IsValidIterator( it ) ); + if ( !IsValidIterator( it ) ) + return false; + + if ( IsInBlock( i, it.m_pBlockHeader ) ) + return i > GetIndex( it ); + + for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext ) + { + if ( IsInBlock( i, pbh ) ) + return true; + } + return false; + } + bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; } + Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); } + + // element access + T& operator[]( int i ); + const T& operator[]( int i ) const; + T& Element( int i ); + const T& Element( int i ) const; + + // Can we use this index? + bool IsIdxValid( int i ) const; + + // Specify the invalid ('null') index that we'll only return on failure + static const int INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT + static int InvalidIndex() { return INVALID_INDEX; } + + // Size + int NumAllocated() const; + int Count() const { return NumAllocated(); } + + // Grows memory by max(num,growsize), and returns the allocation index/ptr + void Grow( int num = 1 ); + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ); + + // Memory deallocation + void Purge(); + +protected: + // Fast swap - WARNING: Swap invalidates all ptr-based indices!!! + void Swap( CUtlFixedMemory< T > &mem ); + + bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const + { + T *p = ( T* )i; + const T *p0 = HeaderToBlock( pBlockHeader ); + return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize; + } + + struct BlockHeader_t + { + BlockHeader_t *m_pNext; + int m_nBlockSize; + }; + + const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); } + const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; } + + BlockHeader_t* m_pBlocks; + int m_nAllocationCount; + int m_nGrowSize; +}; + +//----------------------------------------------------------------------------- +// constructor, destructor +//----------------------------------------------------------------------------- + +template< class T > +CUtlFixedMemory<T>::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount ) +: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 ) +{ + Init( nGrowSize, nInitAllocationCount ); +} + +template< class T > +CUtlFixedMemory<T>::~CUtlFixedMemory() +{ + Purge(); +} + + +//----------------------------------------------------------------------------- +// Fast swap - WARNING: Swap invalidates all ptr-based indices!!! +//----------------------------------------------------------------------------- +template< class T > +void CUtlFixedMemory<T>::Swap( CUtlFixedMemory< T > &mem ) +{ + V_swap( m_pBlocks, mem.m_pBlocks ); + V_swap( m_nAllocationCount, mem.m_nAllocationCount ); + V_swap( m_nGrowSize, mem.m_nGrowSize ); +} + + +//----------------------------------------------------------------------------- +// Set the size by which the memory grows - round up to the next power of 2 +//----------------------------------------------------------------------------- +template< class T > +void CUtlFixedMemory<T>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ ) +{ + Purge(); + + m_nGrowSize = nGrowSize; + + Grow( nInitSize ); +} + +//----------------------------------------------------------------------------- +// element access +//----------------------------------------------------------------------------- +template< class T > +inline T& CUtlFixedMemory<T>::operator[]( int i ) +{ + Assert( IsIdxValid(i) ); + return *( T* )i; +} + +template< class T > +inline const T& CUtlFixedMemory<T>::operator[]( int i ) const +{ + Assert( IsIdxValid(i) ); + return *( T* )i; +} + +template< class T > +inline T& CUtlFixedMemory<T>::Element( int i ) +{ + Assert( IsIdxValid(i) ); + return *( T* )i; +} + +template< class T > +inline const T& CUtlFixedMemory<T>::Element( int i ) const +{ + Assert( IsIdxValid(i) ); + return *( T* )i; +} + + +//----------------------------------------------------------------------------- +// Size +//----------------------------------------------------------------------------- +template< class T > +inline int CUtlFixedMemory<T>::NumAllocated() const +{ + return m_nAllocationCount; +} + + +//----------------------------------------------------------------------------- +// Is element index valid? +//----------------------------------------------------------------------------- +template< class T > +inline bool CUtlFixedMemory<T>::IsIdxValid( int i ) const +{ +#ifdef _DEBUG + for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext ) + { + if ( IsInBlock( i, pbh ) ) + return true; + } + return false; +#else + return i != InvalidIndex(); +#endif +} + +template< class T > +void CUtlFixedMemory<T>::Grow( int num ) +{ + if ( num <= 0 ) + return; + + int nBlockSize = m_nGrowSize; + if ( nBlockSize == 0 ) + { + if ( m_nAllocationCount ) + { + nBlockSize = m_nAllocationCount; + } + else + { + // Compute an allocation which is at least as big as a cache line... + nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T ); + Assert( nBlockSize ); + } + } + if ( nBlockSize < num ) + { + int n = ( num + nBlockSize -1 ) / nBlockSize; + Assert( n * nBlockSize >= num ); + Assert( ( n - 1 ) * nBlockSize < num ); + nBlockSize *= n; + } + m_nAllocationCount += nBlockSize; + + MEM_ALLOC_CREDIT_CLASS(); + BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) ); + if ( !pBlockHeader ) + { + Error( "CUtlFixedMemory overflow!\n" ); + } + pBlockHeader->m_pNext = NULL; + pBlockHeader->m_nBlockSize = nBlockSize; + + if ( !m_pBlocks ) + { + m_pBlocks = pBlockHeader; + } + else + { +#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end + BlockHeader_t * RESTRICT pbh = m_pBlocks; + while ( pbh->m_pNext ) + { + pbh = pbh->m_pNext; + } + pbh->m_pNext = pBlockHeader; +#else + pBlockHeader = m_pBlocks; + pBlockHeader->m_pNext = m_pBlocks; +#endif + } +} + + +//----------------------------------------------------------------------------- +// Makes sure we've got at least this much memory +//----------------------------------------------------------------------------- +template< class T > +inline void CUtlFixedMemory<T>::EnsureCapacity( int num ) +{ + Grow( num - NumAllocated() ); +} + + +//----------------------------------------------------------------------------- +// Memory deallocation +//----------------------------------------------------------------------------- +template< class T > +void CUtlFixedMemory<T>::Purge() +{ + if ( !m_pBlocks ) + return; + + for ( BlockHeader_t *pbh = m_pBlocks; pbh; ) + { + BlockHeader_t *pFree = pbh; + pbh = pbh->m_pNext; + free( pFree ); + } + m_pBlocks = NULL; + m_nAllocationCount = 0; +} + +#include "tier0/memdbgoff.h" + +#endif // UTLFIXEDMEMORY_H |