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:
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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() )
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user