1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-19 03:56:10 +08:00

Update CRawAllocator, CUtlMemoryBlockAllocator & Add CUtlVectorRawAllocator

This commit is contained in:
GAMMACASE
2025-06-05 17:46:47 +03:00
parent 313ed9772d
commit da75324291
6 changed files with 322 additions and 170 deletions

View File

@ -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<MemPage_t, CUtlMemory_RawAllocator<MemPage_t>> MemPagesVec_t;
typedef CUtlVectorRawAllocator<MemPage_t> 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;
}

View File

@ -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

View File

@ -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 KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t, typename TableT = CUtlMemory< CUtlHashtableEntry< KeyT, ValueT > > >
template <typename KeyT, typename ValueT = empty_t, typename KeyHashT = DefaultHashFunctor<KeyT>, typename KeyIsEqualT = DefaultEqualFunctor<KeyT>, typename AlternateKeyT = typename ArgumentTypeInfo<KeyT>::Alt_t, typename TableT = CUtlVectorRawAllocator<CUtlHashtableEntry<KeyT, ValueT>>>
class CUtlHashtable
{
public:
@ -115,7 +114,7 @@ protected:
typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
typedef CUtlHashtableEntry< KeyT, ValueT > entry_t;
typedef CUtlHashtableEntry<KeyT, ValueT> 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<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::DoReal
{
Assert( !m_bSizeLocked );
CUtlMemory_RawAllocator<entry_t> oldTable;
entry_t * RESTRICT pOldBase = NULL;
CUtlMemoryConservative<entry_t> 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<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::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<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::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<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::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<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::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() )

View File

@ -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<T,I>::CUtlMemory( int nGrowSize, int nInitAllocationCount, RawAllocatorType_t eAllocatorType ) : m_pMemory(0),
CUtlMemory<T,I>::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<T, nAlignment>::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<T>::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<T>::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<T>::~CUtlMemory_RawAllocator()
template< class T >
void CUtlMemory_RawAllocator<T>::Swap( CUtlMemory_RawAllocator<T> &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<T>::AssumeMemory( T* pMemory, int numElements, RawAllocatorType_t eAllocatorType )
void CUtlMemory_RawAllocator<T>::AssumeMemory( T* pMemory, int numElements )
{
// Blow away any existing allocated memory
Purge();
@ -1152,8 +1136,6 @@ void CUtlMemory_RawAllocator<T>::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<T>::Detach()
return (T*)DetachMemory();
}
template< class T >
void CUtlMemory_RawAllocator<T>::SetGrowSize( int nSize )
{
m_nGrowSize |= nSize & ~(PLATFORM_ALLOC_MARKER | UNUSED_MARKER);
}
//-----------------------------------------------------------------------------
// Grows the memory
//-----------------------------------------------------------------------------
@ -1184,13 +1160,6 @@ template< class T >
void CUtlMemory_RawAllocator<T>::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<T>::Grow( int num )
template< class T >
inline void CUtlMemory_RawAllocator<T>::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<T>::EnsureCapacity( int num )
template< class T >
void CUtlMemory_RawAllocator<T>::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<T>::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<T>::GetRawAllocatorType() const
{
return ( RawAllocatorType_t )( ( m_nGrowSize & PLATFORM_ALLOC_MARKER ) != 0 );
}
template< class T >
void CUtlMemory_RawAllocator<T>::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"

View File

@ -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<UtlSymLargeId_t, empty_t, UtlSymTableLargeHashFunctor, UtlSymTableLargeEqualFunctor, UtlSymTableLargeAltKey, CUtlMemory_RawAllocator<CUtlHashtableEntry<UtlSymLargeId_t, empty_t>>> Hashtable_t;
typedef CUtlVector< MemBlockHandle_t, CUtlMemory_RawAllocator<MemBlockHandle_t> > MemBlocksVec_t;
typedef CUtlHashtable<UtlSymLargeId_t, empty_t, UtlSymTableLargeHashFunctor, UtlSymTableLargeEqualFunctor, UtlSymTableLargeAltKey> Hashtable_t;
typedef CUtlVectorRawAllocator< MemBlockHandle_t > MemBlocksVec_t;
Hashtable_t m_HashTable;
MemBlocksVec_t m_MemBlocks;

View File

@ -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<T> >
{
typedef CUtlVector< T, CUtlMemory_RawAllocator<T> > 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<T, A>::CUtlVector( int growSize, int initSize, RawAllocatorType_t allocatorType ) :
inline CUtlVector<T, A>::CUtlVector( int growSize, int initSize ) :
m_Size(0), m_Memory(growSize, initSize)
{
}
@ -605,6 +622,43 @@ inline const T& CUtlVector<T, A>::Tail() const
return m_Memory[ m_Size - 1 ];
}
//-----------------------------------------------------------------------------
// Attaches the buffer to external memory....
//-----------------------------------------------------------------------------
template< class T, class A >
inline void CUtlVector<T, A>::SetExternalBuffer( T *pMemory, int allocationCount, int numElements )
{
m_Memory.SetExternalBuffer( pMemory, allocationCount );
m_Size = numElements;
}
template< class T, class A >
void CUtlVector<T, A>::SetExternalBuffer( const T *pMemory, int allocationCount, int numElements )
{
m_Memory.SetExternalBuffer( pMemory, allocationCount );
m_Size = numElements;
}
template< class T, class A >
inline void CUtlVector<T, A>::AssumeMemory( T *pMemory, int allocationCount, int numElements )
{
m_Memory.AssumeMemory( pMemory, allocationCount );
m_Size = numElements;
}
template< typename T, class A >
inline T *CUtlVector<T, A>::Detach()
{
m_Size = 0;
return m_Memory.Detach();
}
template< typename T, class A >
inline void *CUtlVector<T, A>::DetachMemory()
{
m_Size = 0;
return m_Memory.DetachMemory();
}
//-----------------------------------------------------------------------------
// Count