From bdb915aaaed9ec75353ac649f108f2fab8be8894 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Thu, 5 Jun 2025 17:46:47 +0300 Subject: [PATCH] Update CRawAllocator, CUtlMemoryBlockAllocator & Add CUtlVectorRawAllocator --- public/tier1/memblockallocator.h | 202 ++++++++++++++++++++++++++++--- public/tier1/rawallocator.h | 32 +++-- public/tier1/utlhashtable.h | 47 +++---- public/tier1/utlmemory.h | 141 +++++---------------- public/tier1/utlsymbollarge.h | 12 +- public/tier1/utlvector.h | 58 ++++++++- 6 files changed, 322 insertions(+), 170 deletions(-) diff --git a/public/tier1/memblockallocator.h b/public/tier1/memblockallocator.h index 222a9ffa..96d5232c 100644 --- a/public/tier1/memblockallocator.h +++ b/public/tier1/memblockallocator.h @@ -18,55 +18,219 @@ #pragma once #endif +#include "tier1/rawallocator.h" #include "tier1/utlvector.h" +// AMNOTE: Handle that contains page/subpage indexes to allocated memory within internal storage +// Stored in the following format: +// offset within page of size MEMBLOCK_PAGEOFFSET_BIT +// page index of size MEMBLOCK_PAGEINDEX_BIT typedef unsigned int MemBlockHandle_t; #define MEMBLOCKHANDLE_INVALID ((MemBlockHandle_t)~0) +#define MEMBLOCK_DEFAULT_PAGESIZE (0x800) +#define MEMBLOCK_PAGESIZE_SECTION1 (0x10000) +#define MEMBLOCK_PAGESIZE_SECTION2 (0x80000) + +#define MEMBLOCK_PAGEINDEX_BIT (11) +#define MEMBLOCK_PAGEINDEX_MASK ((1 << MEMBLOCK_PAGEINDEX_BIT) - 1) + +#define MEMBLOCK_PAGEOFFSET_BIT (21) +#define MEMBLOCK_PAGEOFFSET_MASK ((1 << MEMBLOCK_PAGEOFFSET_BIT) - 1) + class CUtlMemoryBlockAllocator { public: - DLL_CLASS_IMPORT CUtlMemoryBlockAllocator( int nInitPages, unsigned int nPageSize, RawAllocatorType_t eAllocatorType ); - DLL_CLASS_IMPORT ~CUtlMemoryBlockAllocator( void ); + CUtlMemoryBlockAllocator( int nInitPages = 0, unsigned int nPageSize = MEMBLOCK_DEFAULT_PAGESIZE ) : + m_nPageIndexBits( MEMBLOCK_PAGEINDEX_BIT ), + m_nPageIndexMask( MEMBLOCK_PAGEINDEX_MASK ), + m_nPageOffsetBits( MEMBLOCK_PAGEOFFSET_BIT ), + m_nPageOffsetMask( MEMBLOCK_PAGEOFFSET_MASK ), + m_MemPages( 0, nInitPages ), + m_nPageSize( nPageSize ) + {} - DLL_CLASS_IMPORT void RemoveAll( size_t nSize = 0 ); - DLL_CLASS_IMPORT void Purge( void ); - DLL_CLASS_IMPORT MemBlockHandle_t Alloc( unsigned int nSize ); - DLL_CLASS_IMPORT MemBlockHandle_t AllocAndCopy( const char* pBuf, unsigned int nSize ); - DLL_CLASS_IMPORT size_t MemUsage( void ) const; - DLL_CLASS_IMPORT void SetPageSize( unsigned int nPageSize ); + ~CUtlMemoryBlockAllocator( void ) + { + Purge(); + } - void* GetBlock( MemBlockHandle_t handle ) const; + uint32 MaxPages() const { return (1 << m_nPageIndexBits); } + uint32 MaxPageSize() const { return (1 << m_nPageOffsetBits); } + + // Clears all memory buffers preserving only nSize bytes, which would be treated like a fresh memory + void RemoveAll( size_t nSize = 0 ); + void Purge( void ); + + MemBlockHandle_t Alloc( unsigned int nSize ); + + size_t MemUsage( void ) const; + + void SetPageSize( unsigned int nPageSize ); + + void* GetBlock( MemBlockHandle_t handle ) const; private: - DLL_CLASS_IMPORT int FindPageWithSpace( unsigned int nSpace ) const; + MemBlockHandle_t CreateHandle( int page_idx ) const + { + Assert( page_idx >= 0 && page_idx < m_MemPages.Count() ); + return (m_MemPages[page_idx].m_nUsedSize & m_nPageOffsetMask) | ((page_idx & m_nPageIndexMask) << m_nPageOffsetBits); + } + + int GetPageIdxFromHandle( MemBlockHandle_t handle ) const { return (handle >> m_nPageOffsetBits) & m_nPageIndexMask; } + int GetPageOffsetFromHandle( MemBlockHandle_t handle ) const { return handle & m_nPageOffsetMask; } + + int CalcPageSize( int page_idx, int requested_size ) const; + int FindPageWithSpace( unsigned int nSize ) const; struct MemPage_t { + unsigned int MemoryLeft() const { return m_nTotalSize - m_nUsedSize; } + unsigned int m_nTotalSize; unsigned int m_nUsedSize; - byte* m_pMemory; + byte *m_pMemory; }; - typedef CUtlVector> MemPagesVec_t; + typedef CUtlVectorRawAllocator MemPagesVec_t; - unsigned int m_nMaxPagesExp; + unsigned int m_nPageIndexBits; unsigned int m_nPageIndexMask; - unsigned int m_nPageIndexShift; - unsigned int m_nBlockOffsetMask; + unsigned int m_nPageOffsetBits; + unsigned int m_nPageOffsetMask; MemPagesVec_t m_MemPages; unsigned int m_nPageSize; - RawAllocatorType_t m_eRawAllocatorType; }; +inline void CUtlMemoryBlockAllocator::RemoveAll( size_t nSize ) +{ + size_t accumulated_total = 0; + int removed_at = -1; + + FOR_EACH_VEC( m_MemPages, i ) + { + accumulated_total += m_MemPages[i].m_nTotalSize; + + if(removed_at != -1 || nSize && accumulated_total > nSize) + { + CRawAllocator::Free( m_MemPages[i].m_pMemory ); + + if(removed_at == -1) + removed_at = i; + } + else + { + m_MemPages[i].m_nUsedSize = 0; + } + } + + if(removed_at != -1) + { + m_MemPages.RemoveMultipleFromTail( m_MemPages.Count() - removed_at ); + } +} + +inline void CUtlMemoryBlockAllocator::Purge( void ) +{ + FOR_EACH_VEC( m_MemPages, i ) + { + CRawAllocator::Free( m_MemPages[i].m_pMemory ); + } + + m_MemPages.Purge(); +} + +inline MemBlockHandle_t CUtlMemoryBlockAllocator::Alloc( unsigned int nSize ) +{ + int page_idx = FindPageWithSpace( nSize ); + + // Allocate new page since we can't fit in existing ones + if(page_idx == -1) + { + if(m_MemPages.Count() >= MaxPages()) + return MEMBLOCKHANDLE_INVALID; + + page_idx = m_MemPages.AddToTail(); + int page_size = CalcPageSize( page_idx, nSize ); + + size_t adjusted_size = 0; + auto &page = m_MemPages[page_idx]; + + page.m_pMemory = (byte *)CRawAllocator::Alloc( page_size, &adjusted_size ); + page.m_nTotalSize = adjusted_size; + page.m_nUsedSize = 0; + } + + MemBlockHandle_t handle = CreateHandle( page_idx ); + m_MemPages[page_idx].m_nUsedSize += nSize; + + return handle; +} + +inline size_t CUtlMemoryBlockAllocator::MemUsage( void ) const +{ + size_t mem_usage = 0; + + FOR_EACH_VEC( m_MemPages, i ) + { + mem_usage += m_MemPages[i].m_nTotalSize; + } + + return mem_usage; +} + +inline void CUtlMemoryBlockAllocator::SetPageSize( unsigned int nPageSize ) +{ + if(nPageSize > MEMBLOCK_DEFAULT_PAGESIZE) + m_nPageSize = MIN( nPageSize, MaxPageSize() ); + else + m_nPageSize = MEMBLOCK_DEFAULT_PAGESIZE; +} + +inline int CUtlMemoryBlockAllocator::CalcPageSize( int page_idx, int requested_size ) const +{ + int page_size = MEMBLOCK_DEFAULT_PAGESIZE; + if(page_idx >= 8) + { + if(page_idx >= 16) + page_size = MEMBLOCK_PAGESIZE_SECTION2; + else + page_size = MEMBLOCK_PAGESIZE_SECTION1; + } + + page_size = MAX( page_size, m_nPageSize ); + return MAX( page_size, requested_size ); +} + +inline int CUtlMemoryBlockAllocator::FindPageWithSpace( unsigned int nSize ) const +{ + if(m_MemPages.Count() > 0) + { + if(nSize <= m_MemPages.Tail().MemoryLeft()) + { + return m_MemPages.Count() - 1; + } + else + { + FOR_EACH_VEC( m_MemPages, i ) + { + if(nSize <= m_MemPages[i].MemoryLeft()) + return i; + } + } + } + + return -1; +} + inline void* CUtlMemoryBlockAllocator::GetBlock( MemBlockHandle_t handle ) const { - int nPageIndex = handle >> m_nPageIndexShift; - int nBlockOffset = handle & m_nBlockOffsetMask; + int nPageIndex = GetPageIdxFromHandle( handle ); + int nPageOffset = GetPageOffsetFromHandle( handle ); if ( nPageIndex >= 0 && nPageIndex < m_MemPages.Count() ) - return (void*)&m_MemPages[ nPageIndex ].m_pMemory[ nBlockOffset ]; + return (void*)&m_MemPages[ nPageIndex ].m_pMemory[ nPageOffset ]; return NULL; } diff --git a/public/tier1/rawallocator.h b/public/tier1/rawallocator.h index 0ecbe398..c347faaa 100644 --- a/public/tier1/rawallocator.h +++ b/public/tier1/rawallocator.h @@ -18,17 +18,35 @@ #pragma once #endif -enum RawAllocatorType_t : uint8 -{ - RawAllocator_Standard = 0, - RawAllocator_Platform = 1, -}; +#include "platform.h" +#include "basetypes.h" + +#include "memdbgon.h" class CRawAllocator { public: - DLL_CLASS_IMPORT static void* Alloc( RawAllocatorType_t eAllocatorType, size_t nSize, size_t* nAdjustedSize ); - DLL_CLASS_IMPORT static void Free( RawAllocatorType_t eAllocatorType, void* pMem, size_t nSize ); + static void* Alloc( size_t nSize, size_t *nAdjustedSize ) + { + void *ptr = malloc( nSize ); + *nAdjustedSize = MAX( _msize( ptr ), nSize ); + return ptr; + } + + static void* Realloc( void *base, size_t nSize, size_t *nAdjustedSize ) + { + void *ptr = realloc( base, nSize ); + *nAdjustedSize = MAX( _msize( ptr ), nSize ); + return ptr; + } + + static void Free( void* pMem ) + { + if(pMem) + free( pMem ); + } }; +#include "memdbgoff.h" + #endif // RAWALLOCATOR_H diff --git a/public/tier1/utlhashtable.h b/public/tier1/utlhashtable.h index c2d686df..2fdfadb5 100644 --- a/public/tier1/utlhashtable.h +++ b/public/tier1/utlhashtable.h @@ -74,14 +74,14 @@ public: }; storage_t flags_and_hash; - alignas( MAX( alignof(KVPair), alignof(storage_t) ) ) storage_t data[ ( sizeof(KVPair) + sizeof(storage_t) - 1 ) / sizeof(storage_t) ]; + AlignedByteArrayExplicit_t<(sizeof( KVPair ) + sizeof( storage_t ) - 1) / sizeof( storage_t ), storage_t, MAX( alignof(KVPair), alignof(storage_t) )> data; bool IsValid() const { return flags_and_hash >= 0; } void MarkInvalid() { int32 flag = FLAG_FREE; flags_and_hash = (storage_t)flag; } - const KVPair *Raw() const { return reinterpret_cast< const KVPair * >( &data[0] ); } - const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >( &data[0] ); } - KVPair *Raw() { return reinterpret_cast< KVPair * >( &data[0] ); } - KVPair *operator->() { Assert( IsValid() ); return reinterpret_cast< KVPair * >( &data[0] ); } + const KVPair *Raw() const { return reinterpret_cast< const KVPair * >(data.Base()); } + const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >(data.Base()); } + KVPair *Raw() { return reinterpret_cast< KVPair * >(data.Base()); } + KVPair *operator->() { Assert( IsValid() ); return reinterpret_cast< KVPair * >(data.Base()); } // Returns the ideal index of the data in this slot, or all bits set if invalid uint32 FORCEINLINE IdealIndex( uint32 slotmask ) const { return IdealIndex( flags_and_hash, slotmask ) | ( (int32)flags_and_hash >> 31 ); } @@ -99,12 +99,11 @@ public: // More efficient than memcpy for the small types that are stored in a hashtable void MoveDataFrom( CUtlHashtableEntry &src ) { - storage_t * RESTRICT srcData = &src.data[0]; - for ( int i = 0; i < ARRAYSIZE( data ); ++i ) { data[i] = srcData[i]; } + for ( int i = 0; i < data.Count(); ++i ) { data[i] = src.data[i]; } } }; -template , typename KeyIsEqualT = DefaultEqualFunctor, typename AlternateKeyT = typename ArgumentTypeInfo::Alt_t, typename TableT = CUtlMemory< CUtlHashtableEntry< KeyT, ValueT > > > +template , typename KeyIsEqualT = DefaultEqualFunctor, typename AlternateKeyT = typename ArgumentTypeInfo::Alt_t, typename TableT = CUtlVectorRawAllocator>> class CUtlHashtable { public: @@ -115,7 +114,7 @@ protected: typedef typename ArgumentTypeInfo::Arg_t KeyArg_t; typedef typename ArgumentTypeInfo::Arg_t ValueArg_t; typedef typename ArgumentTypeInfo::Arg_t KeyAlt_t; - typedef CUtlHashtableEntry< KeyT, ValueT > entry_t; + typedef CUtlHashtableEntry entry_t; enum { @@ -163,8 +162,8 @@ public: explicit CUtlHashtable( int minimumSize = 32 ) : m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { InitTable(); } - CUtlHashtable( int nInitSize, RawAllocatorType_t eAllocatorType, int minimumSize = 32 ) - : m_table(0, nInitSize, eAllocatorType), m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { InitTable(); } + CUtlHashtable( int nInitSize, int minimumSize ) + : m_table(0, nInitSize), m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { InitTable(); } CUtlHashtable( int minimumSize, const KeyHashT &hash, KeyIsEqualT const &eq = KeyIsEqualT() ) : m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(eq), m_hash(hash) { InitTable(); } @@ -318,19 +317,11 @@ void CUtlHashtable::DoReal { Assert( !m_bSizeLocked ); - CUtlMemory_RawAllocator oldTable; - entry_t * RESTRICT pOldBase = NULL; + CUtlMemoryConservative oldTable; + entry_t * RESTRICT pOldBase = m_table.Detach(); int nOldSize = m_nTableSize; - if ( !m_table.IsExternallyAllocated() ) - { - int tableSize = m_table.Count(); - pOldBase = m_table.Detach(); - - if ( pOldBase ) - oldTable.AssumeMemory( pOldBase, tableSize, m_table.GetRawAllocatorType() ); - } - else + if (!pOldBase) { if ( nOldSize > 0 ) { @@ -338,15 +329,15 @@ void CUtlHashtable::DoReal if ( nBytes >= 0x4000 ) { - pOldBase = (entry_t *)malloc( nBytes ); - oldTable.AssumeMemory( pOldBase, nOldSize, RawAllocator_Standard ); + oldTable.EnsureCapacity( nOldSize ); + pOldBase = oldTable.Base(); } else { pOldBase = (entry_t *)stackalloc( nBytes ); } - memcpy( pOldBase, m_table.Base(), nBytes ); + V_memmove( pOldBase, m_table.Base(), nBytes ); } m_table.Purge(); @@ -356,7 +347,7 @@ void CUtlHashtable::DoReal Assert( size > 0 && (uint)size <= entry_t::IdealIndex( ~0, 0x1FFFFFFF ) ); // reasonable power of 2 Assert( size > m_nUsed ); - m_table.EnsureCapacity( size ); + m_table.EnsureCount( size ); // correct the size if we have allocated more than required while ( size <= INT_MAX/2 ) @@ -466,7 +457,7 @@ int CUtlHashtable::DoInser if ( allowGrow && !m_bSizeLocked ) { // Keep the load factor between .25 and .75 - int newSize = m_nUsed + 1; + int newSize = m_nUsed + 4; if ( newSize*4 > m_nTableSize*3 ) { DoRealloc( newSize * 4 / 3 ); @@ -714,7 +705,7 @@ void CUtlHashtable::Remove int used = m_nUsed; if ( used != 0 ) { - entry_t* table = m_table.Base(); + entry_t* table = m_table.Base(); for ( int i = m_nTableSize - 1; i >= 0; --i ) { if ( table[i].IsValid() ) diff --git a/public/tier1/utlmemory.h b/public/tier1/utlmemory.h index 2b461ff2..44e3efaf 100644 --- a/public/tier1/utlmemory.h +++ b/public/tier1/utlmemory.h @@ -53,7 +53,7 @@ class CUtlMemory { public: // constructor, destructor - CUtlMemory( int nGrowSize = 0, int nInitSize = 0, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ); + CUtlMemory( int nGrowSize = 0, int nInitSize = 0 ); CUtlMemory( T* pMemory, int numElements ); CUtlMemory( const T* pMemory, int numElements ); ~CUtlMemory(); @@ -133,8 +133,6 @@ public: // Set the size by which the memory grows void SetGrowSize( int size ); - RawAllocatorType_t GetRawAllocatorType() const { return RawAllocator_Standard; }; - protected: void ValidateGrowSize() { @@ -388,7 +386,7 @@ private: //----------------------------------------------------------------------------- template< class T, class I > -CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount, RawAllocatorType_t eAllocatorType ) : m_pMemory(0), +CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0), m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize & ~(EXTERNAL_CONST_BUFFER_MARKER | EXTERNAL_BUFFER_MARKER) ) { ValidateGrowSize(); @@ -1028,13 +1026,14 @@ void CUtlMemoryAligned::Purge() } } +#pragma pack(push, 1) template< class T > class CUtlMemory_RawAllocator { public: // constructor, destructor - CUtlMemory_RawAllocator( int nGrowSize = 0, int nInitSize = 0, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ); - CUtlMemory_RawAllocator( T* pMemory, int numElements ) { Assert( 0 ); } + CUtlMemory_RawAllocator( int nGrowSize = 0, int nInitSize = 0 ); + CUtlMemory_RawAllocator( T *pMemory, int numElements ) { Assert( 0 ); } ~CUtlMemory_RawAllocator(); // Can we use this index? @@ -1042,8 +1041,8 @@ public: static int InvalidIndex() { return -1; } // Gets the base address (can change when adding elements!) - T* Base() { return m_pMemory; } - const T* Base() const { return m_pMemory; } + T* Base() { return m_nAllocationCount > 0 ? m_pMemory : nullptr; } + const T* Base() const { return m_nAllocationCount > 0 ? m_pMemory : nullptr; } // element access T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } @@ -1053,7 +1052,7 @@ public: // Attaches the buffer to external memory.... void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } - void AssumeMemory( T *pMemory, int nSize, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ); + void AssumeMemory( T *pMemory, int nSize ); T* Detach(); void *DetachMemory(); @@ -1079,11 +1078,6 @@ public: // is the memory externally allocated? bool IsExternallyAllocated() const { return false; } - // Set the size by which the memory grows - void SetGrowSize( int size ); - - RawAllocatorType_t GetRawAllocatorType() const; - class Iterator_t { public: @@ -1100,18 +1094,10 @@ public: Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } private: - void SetRawAllocatorType( RawAllocatorType_t eAllocatorType ); - - enum - { - PLATFORM_ALLOC_MARKER = (1 << 30), - UNUSED_MARKER = (1 << 31), - }; - - T* m_pMemory; int m_nAllocationCount; - int m_nGrowSize; + T* m_pMemory; }; +#pragma pack(pop) //----------------------------------------------------------------------------- @@ -1119,11 +1105,10 @@ private: //----------------------------------------------------------------------------- template< class T > -CUtlMemory_RawAllocator::CUtlMemory_RawAllocator( int nGrowSize, int nInitAllocationCount, RawAllocatorType_t eAllocatorType ) : m_pMemory(0), - m_nAllocationCount(0), m_nGrowSize(nGrowSize & ~(PLATFORM_ALLOC_MARKER | UNUSED_MARKER)) +CUtlMemory_RawAllocator::CUtlMemory_RawAllocator( int nGrowSize, int nInitSize ) + : m_nAllocationCount( 0 ), m_pMemory( nullptr ) { - SetRawAllocatorType( eAllocatorType ); - EnsureCapacity( nInitAllocationCount ); + EnsureCapacity( nInitSize ); } template< class T > @@ -1138,13 +1123,12 @@ CUtlMemory_RawAllocator::~CUtlMemory_RawAllocator() template< class T > void CUtlMemory_RawAllocator::Swap( CUtlMemory_RawAllocator &mem ) { - V_swap( m_nGrowSize, mem.m_nGrowSize ); V_swap( m_pMemory, mem.m_pMemory ); V_swap( m_nAllocationCount, mem.m_nAllocationCount ); } template< class T > -void CUtlMemory_RawAllocator::AssumeMemory( T* pMemory, int numElements, RawAllocatorType_t eAllocatorType ) +void CUtlMemory_RawAllocator::AssumeMemory( T* pMemory, int numElements ) { // Blow away any existing allocated memory Purge(); @@ -1152,8 +1136,6 @@ void CUtlMemory_RawAllocator::AssumeMemory( T* pMemory, int numElements, RawA // Simply take the pointer but don't mark us as external m_pMemory = pMemory; m_nAllocationCount = numElements; - - SetRawAllocatorType( eAllocatorType ); } template< class T > @@ -1171,12 +1153,6 @@ inline T* CUtlMemory_RawAllocator::Detach() return (T*)DetachMemory(); } -template< class T > -void CUtlMemory_RawAllocator::SetGrowSize( int nSize ) -{ - m_nGrowSize |= nSize & ~(PLATFORM_ALLOC_MARKER | UNUSED_MARKER); -} - //----------------------------------------------------------------------------- // Grows the memory //----------------------------------------------------------------------------- @@ -1184,13 +1160,6 @@ template< class T > void CUtlMemory_RawAllocator::Grow( int num ) { Assert( num > 0 ); - - if ( ( INT_MAX - m_nAllocationCount ) < num ) - { - Plat_FatalErrorFunc( "%s: Invalid grow amount %d\n", __FUNCTION__, num ); - DebuggerBreak(); - } - EnsureCapacity( m_nAllocationCount + num ); } @@ -1200,28 +1169,17 @@ void CUtlMemory_RawAllocator::Grow( int num ) template< class T > inline void CUtlMemory_RawAllocator::EnsureCapacity( int num ) { - if (m_nAllocationCount >= num) + if(m_nAllocationCount >= num) return; - - if ( ( size_t )num > ( SIZE_MAX / sizeof(T) ) ) - { - Plat_FatalErrorFunc( "%s: Invalid capacity %u\n", __FUNCTION__, num ); - DebuggerBreak(); - } - - void *pMemory = m_pMemory; - size_t nSize = m_nAllocationCount * sizeof(T); - RawAllocatorType_t eAllocatorType = GetRawAllocatorType(); - size_t adjustedSize; - m_pMemory = (T*)CRawAllocator::Alloc( eAllocatorType, num * sizeof(T), &adjustedSize ); - m_nAllocationCount = ( int )( adjustedSize / sizeof(T) ); + int new_alloc_size = CalcNewDoublingCount( m_nAllocationCount, num, 2, INT_MAX ); + size_t adjusted_size = 0; - if ( pMemory ) - { - memcpy( m_pMemory, pMemory, nSize ); - CRawAllocator::Free( eAllocatorType, pMemory, nSize ); - } + MEM_ALLOC_CREDIT_CLASS(); + m_pMemory = (T *)CRawAllocator::Realloc( m_pMemory, new_alloc_size * sizeof( T ), &adjusted_size ); + m_nAllocationCount = clamp( (int)(adjusted_size / sizeof( T )), new_alloc_size, INT_MAX ); + + UTLMEMORY_TRACK_ALLOC(); } //----------------------------------------------------------------------------- @@ -1230,12 +1188,14 @@ inline void CUtlMemory_RawAllocator::EnsureCapacity( int num ) template< class T > void CUtlMemory_RawAllocator::Purge() { - if (m_pMemory) + if (m_nAllocationCount > 0) { - CRawAllocator::Free( GetRawAllocatorType(), m_pMemory, m_nAllocationCount * sizeof(T) ); + UTLMEMORY_TRACK_FREE(); + CRawAllocator::Free( m_pMemory ); m_pMemory = 0; - m_nAllocationCount = 0; } + + m_nAllocationCount = 0; } template< class T > @@ -1271,49 +1231,14 @@ void CUtlMemory_RawAllocator::Purge( int numElements ) return; } - void *pMemory = m_pMemory; - size_t nSize = m_nAllocationCount * sizeof(T); - RawAllocatorType_t eAllocatorType = GetRawAllocatorType(); + UTLMEMORY_TRACK_FREE(); + size_t adjusted_size = 0; - size_t adjustedSize; - m_pMemory = (T*)CRawAllocator::Alloc( eAllocatorType, numElements * sizeof(T), &adjustedSize ); + MEM_ALLOC_CREDIT_CLASS(); + m_pMemory = (T *)CRawAllocator::Realloc( m_pMemory, numElements * sizeof( T ), &adjusted_size ); + m_nAllocationCount = clamp( (int)(adjusted_size / sizeof( T )), numElements, INT_MAX ); - if ( adjustedSize < nSize ) - { - m_nAllocationCount = ( int )( adjustedSize / sizeof(T) ); - memcpy( m_pMemory, pMemory, adjustedSize ); - CRawAllocator::Free( eAllocatorType, pMemory, nSize ); - } - else - { - CRawAllocator::Free( eAllocatorType, m_pMemory, adjustedSize ); - m_pMemory = pMemory; - } -} - -template< class T > -RawAllocatorType_t CUtlMemory_RawAllocator::GetRawAllocatorType() const -{ - return ( RawAllocatorType_t )( ( m_nGrowSize & PLATFORM_ALLOC_MARKER ) != 0 ); -} - -template< class T > -void CUtlMemory_RawAllocator::SetRawAllocatorType( RawAllocatorType_t eAllocatorType ) -{ - if ( eAllocatorType == RawAllocator_Platform ) - { - m_nGrowSize |= PLATFORM_ALLOC_MARKER; - } - else - { - if ( eAllocatorType != RawAllocator_Standard ) - { - Plat_FatalErrorFunc( "%s: Unsupported raw allocator type %u\n", __FUNCTION__, eAllocatorType ); - DebuggerBreak(); - } - - m_nGrowSize &= ~PLATFORM_ALLOC_MARKER; - } + UTLMEMORY_TRACK_ALLOC(); } #include "tier0/memdbgoff.h" diff --git a/public/tier1/utlsymbollarge.h b/public/tier1/utlsymbollarge.h index 0e839bb4..ee00a889 100644 --- a/public/tier1/utlsymbollarge.h +++ b/public/tier1/utlsymbollarge.h @@ -125,11 +125,11 @@ class CUtlSymbolTableLargeBase { public: // constructor, destructor - CUtlSymbolTableLargeBase( int nGrowSize = 0, int nInitSize = 16, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ) - : m_HashTable( 0, eAllocatorType ), - m_MemBlocks( nGrowSize, nInitSize, eAllocatorType ), + CUtlSymbolTableLargeBase( int nGrowSize = 0, int nInitSize = 16 ) + : m_HashTable( 0 ), + m_MemBlocks( nGrowSize, nInitSize ), m_Mutex( "CUtlSymbolTableLargeBase" ), - m_MemBlockAllocator( ( nInitSize > 0 ) ? 8 : 0, PAGE_SIZE, eAllocatorType ), + m_MemBlockAllocator( ( nInitSize > 0 ) ? 8 : 0, PAGE_SIZE ), m_nElementLimit( INT_MAX - 1 ), m_bThrowError( true ) { } @@ -226,8 +226,8 @@ private: } }; - typedef CUtlHashtable>> Hashtable_t; - typedef CUtlVector< MemBlockHandle_t, CUtlMemory_RawAllocator > MemBlocksVec_t; + typedef CUtlHashtable Hashtable_t; + typedef CUtlVectorRawAllocator< MemBlockHandle_t > MemBlocksVec_t; Hashtable_t m_HashTable; MemBlocksVec_t m_MemBlocks; diff --git a/public/tier1/utlvector.h b/public/tier1/utlvector.h index 8d8bbe59..df0091ff 100644 --- a/public/tier1/utlvector.h +++ b/public/tier1/utlvector.h @@ -45,7 +45,7 @@ public: typedef T ElemType_t; // constructor, destructor - CUtlVector( int growSize = 0, int initSize = 0, RawAllocatorType_t allocatorType = RawAllocator_Standard ); + CUtlVector( int growSize = 0, int initSize = 0 ); CUtlVector( T* pMemory, int allocationCount, int numElements = 0 ); ~CUtlVector(); @@ -66,6 +66,13 @@ public: T* Base() { return m_Memory.Base(); } const T* Base() const { return m_Memory.Base(); } + // Attaches the buffer to external memory.... + void SetExternalBuffer( T *pMemory, int allocationCount, int numElements = 0 ); + void SetExternalBuffer( const T *pMemory, int allocationCount, int numElements = 0 ); + void AssumeMemory( T *pMemory, int allocationCount, int numElements = 0 ); + T *Detach(); + void *DetachMemory(); + // Returns the number of elements in the vector int Count() const; @@ -240,6 +247,16 @@ public: CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} }; +template< class T > +class CUtlVectorRawAllocator : public CUtlVector< T, CUtlMemory_RawAllocator > +{ + typedef CUtlVector< T, CUtlMemory_RawAllocator > BaseClass; +public: + + // constructor, destructor + CUtlVectorRawAllocator( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} + CUtlVectorRawAllocator( T *pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} +}; //----------------------------------------------------------------------------- // The CUtlVectorUltra Conservative class: @@ -516,7 +533,7 @@ public: // constructor, destructor //----------------------------------------------------------------------------- template< typename T, class A > -inline CUtlVector::CUtlVector( int growSize, int initSize, RawAllocatorType_t allocatorType ) : +inline CUtlVector::CUtlVector( int growSize, int initSize ) : m_Size(0), m_Memory(growSize, initSize) { } @@ -605,6 +622,43 @@ inline const T& CUtlVector::Tail() const return m_Memory[ m_Size - 1 ]; } +//----------------------------------------------------------------------------- +// Attaches the buffer to external memory.... +//----------------------------------------------------------------------------- +template< class T, class A > +inline void CUtlVector::SetExternalBuffer( T *pMemory, int allocationCount, int numElements ) +{ + m_Memory.SetExternalBuffer( pMemory, allocationCount ); + m_Size = numElements; +} + +template< class T, class A > +void CUtlVector::SetExternalBuffer( const T *pMemory, int allocationCount, int numElements ) +{ + m_Memory.SetExternalBuffer( pMemory, allocationCount ); + m_Size = numElements; +} + +template< class T, class A > +inline void CUtlVector::AssumeMemory( T *pMemory, int allocationCount, int numElements ) +{ + m_Memory.AssumeMemory( pMemory, allocationCount ); + m_Size = numElements; +} + +template< typename T, class A > +inline T *CUtlVector::Detach() +{ + m_Size = 0; + return m_Memory.Detach(); +} + +template< typename T, class A > +inline void *CUtlVector::DetachMemory() +{ + m_Size = 0; + return m_Memory.DetachMemory(); +} //----------------------------------------------------------------------------- // Count