1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-20 04:26:03 +08:00

Update CRawAllocator, CUtlMemoryBlockAllocator & Add CUtlVectorRawAllocator

This commit is contained in:
GAMMACASE
2025-06-05 17:46:47 +03:00
parent 2ed598b4e2
commit 9cbdadbda5
6 changed files with 322 additions and 170 deletions

View File

@ -18,55 +18,219 @@
#pragma once #pragma once
#endif #endif
#include "tier1/rawallocator.h"
#include "tier1/utlvector.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; typedef unsigned int MemBlockHandle_t;
#define MEMBLOCKHANDLE_INVALID ((MemBlockHandle_t)~0) #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 class CUtlMemoryBlockAllocator
{ {
public: public:
DLL_CLASS_IMPORT CUtlMemoryBlockAllocator( int nInitPages, unsigned int nPageSize, RawAllocatorType_t eAllocatorType ); CUtlMemoryBlockAllocator( int nInitPages = 0, unsigned int nPageSize = MEMBLOCK_DEFAULT_PAGESIZE ) :
DLL_CLASS_IMPORT ~CUtlMemoryBlockAllocator( void ); 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 ); ~CUtlMemoryBlockAllocator( void )
DLL_CLASS_IMPORT void Purge( void ); {
DLL_CLASS_IMPORT MemBlockHandle_t Alloc( unsigned int nSize ); Purge();
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 ); 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; void* GetBlock( MemBlockHandle_t handle ) const;
private: 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 struct MemPage_t
{ {
unsigned int MemoryLeft() const { return m_nTotalSize - m_nUsedSize; }
unsigned int m_nTotalSize; unsigned int m_nTotalSize;
unsigned int m_nUsedSize; 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_nPageIndexMask;
unsigned int m_nPageIndexShift; unsigned int m_nPageOffsetBits;
unsigned int m_nBlockOffsetMask; unsigned int m_nPageOffsetMask;
MemPagesVec_t m_MemPages; MemPagesVec_t m_MemPages;
unsigned int m_nPageSize; 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 inline void* CUtlMemoryBlockAllocator::GetBlock( MemBlockHandle_t handle ) const
{ {
int nPageIndex = handle >> m_nPageIndexShift; int nPageIndex = GetPageIdxFromHandle( handle );
int nBlockOffset = handle & m_nBlockOffsetMask; int nPageOffset = GetPageOffsetFromHandle( handle );
if ( nPageIndex >= 0 && nPageIndex < m_MemPages.Count() ) 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; return NULL;
} }

View File

@ -18,17 +18,35 @@
#pragma once #pragma once
#endif #endif
enum RawAllocatorType_t : uint8 #include "platform.h"
{ #include "basetypes.h"
RawAllocator_Standard = 0,
RawAllocator_Platform = 1, #include "memdbgon.h"
};
class CRawAllocator class CRawAllocator
{ {
public: public:
DLL_CLASS_IMPORT static void* Alloc( RawAllocatorType_t eAllocatorType, size_t nSize, size_t* nAdjustedSize ); static void* Alloc( size_t nSize, size_t *nAdjustedSize )
DLL_CLASS_IMPORT static void Free( RawAllocatorType_t eAllocatorType, void* pMem, size_t nSize ); {
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 #endif // RAWALLOCATOR_H

View File

@ -74,14 +74,14 @@ public:
}; };
storage_t flags_and_hash; 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; } bool IsValid() const { return flags_and_hash >= 0; }
void MarkInvalid() { int32 flag = FLAG_FREE; flags_and_hash = (storage_t)flag; } 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 *Raw() const { return reinterpret_cast< const KVPair * >(data.Base()); }
const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >( &data[0] ); } const KVPair *operator->() const { Assert( IsValid() ); return reinterpret_cast< const KVPair * >(data.Base()); }
KVPair *Raw() { return reinterpret_cast< KVPair * >( &data[0] ); } KVPair *Raw() { return reinterpret_cast< KVPair * >(data.Base()); }
KVPair *operator->() { Assert( IsValid() ); return reinterpret_cast< KVPair * >( &data[0] ); } 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 // 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 ); } 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 // More efficient than memcpy for the small types that are stored in a hashtable
void MoveDataFrom( CUtlHashtableEntry &src ) void MoveDataFrom( CUtlHashtableEntry &src )
{ {
storage_t * RESTRICT srcData = &src.data[0]; for ( int i = 0; i < data.Count(); ++i ) { data[i] = src.data[i]; }
for ( int i = 0; i < ARRAYSIZE( data ); ++i ) { data[i] = srcData[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 class CUtlHashtable
{ {
public: public:
@ -115,7 +114,7 @@ protected:
typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t; typedef typename ArgumentTypeInfo<KeyT>::Arg_t KeyArg_t;
typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t; typedef typename ArgumentTypeInfo<ValueT>::Arg_t ValueArg_t;
typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t; typedef typename ArgumentTypeInfo<AlternateKeyT>::Arg_t KeyAlt_t;
typedef CUtlHashtableEntry< KeyT, ValueT > entry_t; typedef CUtlHashtableEntry<KeyT, ValueT> entry_t;
enum enum
{ {
@ -163,8 +162,8 @@ public:
explicit CUtlHashtable( int minimumSize = 32 ) explicit CUtlHashtable( int minimumSize = 32 )
: m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { InitTable(); } : 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 ) CUtlHashtable( int nInitSize, int minimumSize )
: m_table(0, nInitSize, eAllocatorType), m_nUsed(0), m_nTableSize(0), m_nMinSize(MAX(8, minimumSize)), m_bSizeLocked(false), m_eq(), m_hash() { InitTable(); } : 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() ) 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(); } : 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 ); Assert( !m_bSizeLocked );
CUtlMemory_RawAllocator<entry_t> oldTable; CUtlMemoryConservative<entry_t> oldTable;
entry_t * RESTRICT pOldBase = NULL; entry_t * RESTRICT pOldBase = m_table.Detach();
int nOldSize = m_nTableSize; int nOldSize = m_nTableSize;
if ( !m_table.IsExternallyAllocated() ) if (!pOldBase)
{
int tableSize = m_table.Count();
pOldBase = m_table.Detach();
if ( pOldBase )
oldTable.AssumeMemory( pOldBase, tableSize, m_table.GetRawAllocatorType() );
}
else
{ {
if ( nOldSize > 0 ) if ( nOldSize > 0 )
{ {
@ -338,15 +329,15 @@ void CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::DoReal
if ( nBytes >= 0x4000 ) if ( nBytes >= 0x4000 )
{ {
pOldBase = (entry_t *)malloc( nBytes ); oldTable.EnsureCapacity( nOldSize );
oldTable.AssumeMemory( pOldBase, nOldSize, RawAllocator_Standard ); pOldBase = oldTable.Base();
} }
else else
{ {
pOldBase = (entry_t *)stackalloc( nBytes ); pOldBase = (entry_t *)stackalloc( nBytes );
} }
memcpy( pOldBase, m_table.Base(), nBytes ); V_memmove( pOldBase, m_table.Base(), nBytes );
} }
m_table.Purge(); 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 > 0 && (uint)size <= entry_t::IdealIndex( ~0, 0x1FFFFFFF ) ); // reasonable power of 2
Assert( size > m_nUsed ); Assert( size > m_nUsed );
m_table.EnsureCapacity( size ); m_table.EnsureCount( size );
// correct the size if we have allocated more than required // correct the size if we have allocated more than required
while ( size <= INT_MAX/2 ) while ( size <= INT_MAX/2 )
@ -466,7 +457,7 @@ int CUtlHashtable<KeyT, ValueT, KeyHashT, KeyIsEqualT, AltKeyT, TableT>::DoInser
if ( allowGrow && !m_bSizeLocked ) if ( allowGrow && !m_bSizeLocked )
{ {
// Keep the load factor between .25 and .75 // Keep the load factor between .25 and .75
int newSize = m_nUsed + 1; int newSize = m_nUsed + 4;
if ( newSize*4 > m_nTableSize*3 ) if ( newSize*4 > m_nTableSize*3 )
{ {
DoRealloc( newSize * 4 / 3 ); DoRealloc( newSize * 4 / 3 );

View File

@ -53,7 +53,7 @@ class CUtlMemory
{ {
public: public:
// constructor, destructor // 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( T* pMemory, int numElements );
CUtlMemory( const T* pMemory, int numElements ); CUtlMemory( const T* pMemory, int numElements );
~CUtlMemory(); ~CUtlMemory();
@ -133,8 +133,6 @@ public:
// Set the size by which the memory grows // Set the size by which the memory grows
void SetGrowSize( int size ); void SetGrowSize( int size );
RawAllocatorType_t GetRawAllocatorType() const { return RawAllocator_Standard; };
protected: protected:
void ValidateGrowSize() void ValidateGrowSize()
{ {
@ -388,7 +386,7 @@ private:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template< class T, class I > 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) ) m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize & ~(EXTERNAL_CONST_BUFFER_MARKER | EXTERNAL_BUFFER_MARKER) )
{ {
ValidateGrowSize(); ValidateGrowSize();
@ -1028,13 +1026,14 @@ void CUtlMemoryAligned<T, nAlignment>::Purge()
} }
} }
#pragma pack(push, 1)
template< class T > template< class T >
class CUtlMemory_RawAllocator class CUtlMemory_RawAllocator
{ {
public: public:
// constructor, destructor // constructor, destructor
CUtlMemory_RawAllocator( int nGrowSize = 0, int nInitSize = 0, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ); CUtlMemory_RawAllocator( int nGrowSize = 0, int nInitSize = 0 );
CUtlMemory_RawAllocator( T* pMemory, int numElements ) { Assert( 0 ); } CUtlMemory_RawAllocator( T *pMemory, int numElements ) { Assert( 0 ); }
~CUtlMemory_RawAllocator(); ~CUtlMemory_RawAllocator();
// Can we use this index? // Can we use this index?
@ -1042,8 +1041,8 @@ public:
static int InvalidIndex() { return -1; } static int InvalidIndex() { return -1; }
// Gets the base address (can change when adding elements!) // Gets the base address (can change when adding elements!)
T* Base() { return m_pMemory; } T* Base() { return m_nAllocationCount > 0 ? m_pMemory : nullptr; }
const T* Base() const { return m_pMemory; } const T* Base() const { return m_nAllocationCount > 0 ? m_pMemory : nullptr; }
// element access // element access
T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
@ -1053,7 +1052,7 @@ public:
// Attaches the buffer to external memory.... // Attaches the buffer to external memory....
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } 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(); T* Detach();
void *DetachMemory(); void *DetachMemory();
@ -1079,11 +1078,6 @@ public:
// is the memory externally allocated? // is the memory externally allocated?
bool IsExternallyAllocated() const { return false; } bool IsExternallyAllocated() const { return false; }
// Set the size by which the memory grows
void SetGrowSize( int size );
RawAllocatorType_t GetRawAllocatorType() const;
class Iterator_t class Iterator_t
{ {
public: public:
@ -1100,18 +1094,10 @@ public:
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
private: private:
void SetRawAllocatorType( RawAllocatorType_t eAllocatorType );
enum
{
PLATFORM_ALLOC_MARKER = (1 << 30),
UNUSED_MARKER = (1 << 31),
};
T* m_pMemory;
int m_nAllocationCount; int m_nAllocationCount;
int m_nGrowSize; T* m_pMemory;
}; };
#pragma pack(pop)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1119,11 +1105,10 @@ private:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template< class T > template< class T >
CUtlMemory_RawAllocator<T>::CUtlMemory_RawAllocator( int nGrowSize, int nInitAllocationCount, RawAllocatorType_t eAllocatorType ) : m_pMemory(0), CUtlMemory_RawAllocator<T>::CUtlMemory_RawAllocator( int nGrowSize, int nInitSize )
m_nAllocationCount(0), m_nGrowSize(nGrowSize & ~(PLATFORM_ALLOC_MARKER | UNUSED_MARKER)) : m_nAllocationCount( 0 ), m_pMemory( nullptr )
{ {
SetRawAllocatorType( eAllocatorType ); EnsureCapacity( nInitSize );
EnsureCapacity( nInitAllocationCount );
} }
template< class T > template< class T >
@ -1138,13 +1123,12 @@ CUtlMemory_RawAllocator<T>::~CUtlMemory_RawAllocator()
template< class T > template< class T >
void CUtlMemory_RawAllocator<T>::Swap( CUtlMemory_RawAllocator<T> &mem ) 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_pMemory, mem.m_pMemory );
V_swap( m_nAllocationCount, mem.m_nAllocationCount ); V_swap( m_nAllocationCount, mem.m_nAllocationCount );
} }
template< class T > 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 // Blow away any existing allocated memory
Purge(); 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 // Simply take the pointer but don't mark us as external
m_pMemory = pMemory; m_pMemory = pMemory;
m_nAllocationCount = numElements; m_nAllocationCount = numElements;
SetRawAllocatorType( eAllocatorType );
} }
template< class T > template< class T >
@ -1171,12 +1153,6 @@ inline T* CUtlMemory_RawAllocator<T>::Detach()
return (T*)DetachMemory(); return (T*)DetachMemory();
} }
template< class T >
void CUtlMemory_RawAllocator<T>::SetGrowSize( int nSize )
{
m_nGrowSize |= nSize & ~(PLATFORM_ALLOC_MARKER | UNUSED_MARKER);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Grows the memory // Grows the memory
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1184,13 +1160,6 @@ template< class T >
void CUtlMemory_RawAllocator<T>::Grow( int num ) void CUtlMemory_RawAllocator<T>::Grow( int num )
{ {
Assert( num > 0 ); Assert( num > 0 );
if ( ( INT_MAX - m_nAllocationCount ) < num )
{
Plat_FatalErrorFunc( "%s: Invalid grow amount %d\n", __FUNCTION__, num );
DebuggerBreak();
}
EnsureCapacity( m_nAllocationCount + num ); EnsureCapacity( m_nAllocationCount + num );
} }
@ -1200,28 +1169,17 @@ void CUtlMemory_RawAllocator<T>::Grow( int num )
template< class T > template< class T >
inline void CUtlMemory_RawAllocator<T>::EnsureCapacity( int num ) inline void CUtlMemory_RawAllocator<T>::EnsureCapacity( int num )
{ {
if (m_nAllocationCount >= num) if(m_nAllocationCount >= num)
return; return;
if ( ( size_t )num > ( SIZE_MAX / sizeof(T) ) ) int new_alloc_size = CalcNewDoublingCount( m_nAllocationCount, num, 2, INT_MAX );
{ size_t adjusted_size = 0;
Plat_FatalErrorFunc( "%s: Invalid capacity %u\n", __FUNCTION__, num );
DebuggerBreak();
}
void *pMemory = m_pMemory; MEM_ALLOC_CREDIT_CLASS();
size_t nSize = m_nAllocationCount * sizeof(T); m_pMemory = (T *)CRawAllocator::Realloc( m_pMemory, new_alloc_size * sizeof( T ), &adjusted_size );
RawAllocatorType_t eAllocatorType = GetRawAllocatorType(); m_nAllocationCount = clamp( (int)(adjusted_size / sizeof( T )), new_alloc_size, INT_MAX );
size_t adjustedSize; UTLMEMORY_TRACK_ALLOC();
m_pMemory = (T*)CRawAllocator::Alloc( eAllocatorType, num * sizeof(T), &adjustedSize );
m_nAllocationCount = ( int )( adjustedSize / sizeof(T) );
if ( pMemory )
{
memcpy( m_pMemory, pMemory, nSize );
CRawAllocator::Free( eAllocatorType, pMemory, nSize );
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1230,12 +1188,14 @@ inline void CUtlMemory_RawAllocator<T>::EnsureCapacity( int num )
template< class T > template< class T >
void CUtlMemory_RawAllocator<T>::Purge() 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_pMemory = 0;
m_nAllocationCount = 0;
} }
m_nAllocationCount = 0;
} }
template< class T > template< class T >
@ -1271,49 +1231,14 @@ void CUtlMemory_RawAllocator<T>::Purge( int numElements )
return; return;
} }
void *pMemory = m_pMemory; UTLMEMORY_TRACK_FREE();
size_t nSize = m_nAllocationCount * sizeof(T); size_t adjusted_size = 0;
RawAllocatorType_t eAllocatorType = GetRawAllocatorType();
size_t adjustedSize; MEM_ALLOC_CREDIT_CLASS();
m_pMemory = (T*)CRawAllocator::Alloc( eAllocatorType, numElements * sizeof(T), &adjustedSize ); 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 ) UTLMEMORY_TRACK_ALLOC();
{
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;
}
} }
#include "tier0/memdbgoff.h" #include "tier0/memdbgoff.h"

View File

@ -125,11 +125,11 @@ class CUtlSymbolTableLargeBase
{ {
public: public:
// constructor, destructor // constructor, destructor
CUtlSymbolTableLargeBase( int nGrowSize = 0, int nInitSize = 16, RawAllocatorType_t eAllocatorType = RawAllocator_Standard ) CUtlSymbolTableLargeBase( int nGrowSize = 0, int nInitSize = 16 )
: m_HashTable( 0, eAllocatorType ), : m_HashTable( 0 ),
m_MemBlocks( nGrowSize, nInitSize, eAllocatorType ), m_MemBlocks( nGrowSize, nInitSize ),
m_Mutex( "CUtlSymbolTableLargeBase" ), 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_nElementLimit( INT_MAX - 1 ),
m_bThrowError( true ) { } 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 CUtlHashtable<UtlSymLargeId_t, empty_t, UtlSymTableLargeHashFunctor, UtlSymTableLargeEqualFunctor, UtlSymTableLargeAltKey> Hashtable_t;
typedef CUtlVector< MemBlockHandle_t, CUtlMemory_RawAllocator<MemBlockHandle_t> > MemBlocksVec_t; typedef CUtlVectorRawAllocator< MemBlockHandle_t > MemBlocksVec_t;
Hashtable_t m_HashTable; Hashtable_t m_HashTable;
MemBlocksVec_t m_MemBlocks; MemBlocksVec_t m_MemBlocks;

View File

@ -45,7 +45,7 @@ public:
typedef T ElemType_t; typedef T ElemType_t;
// constructor, destructor // 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( T* pMemory, int allocationCount, int numElements = 0 );
~CUtlVector(); ~CUtlVector();
@ -66,6 +66,13 @@ public:
T* Base() { return m_Memory.Base(); } T* Base() { return m_Memory.Base(); }
const T* Base() const { 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 // Returns the number of elements in the vector
int Count() const; int Count() const;
@ -240,6 +247,16 @@ public:
CUtlVectorConservative( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} 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: // The CUtlVectorUltra Conservative class:
@ -516,7 +533,7 @@ public:
// constructor, destructor // constructor, destructor
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template< typename T, class A > 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) 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 ]; 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 // Count