大改
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include "UtlMemory.hpp"
|
||||
#define _Utl_Vector_assert
|
||||
|
||||
345
csgo2/sdk/tier1/utlblockmemory.h
Normal file
345
csgo2/sdk/tier1/utlblockmemory.h
Normal file
@@ -0,0 +1,345 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A growable memory class.
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef UTLBLOCKMEMORY_H
|
||||
#define UTLBLOCKMEMORY_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
#include "../sdk.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4100)
|
||||
#pragma warning (disable:4514)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef UTBLOCKLMEMORY_TRACK
|
||||
#define UTLBLOCKMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#define UTLBLOCKMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#else
|
||||
#define UTLBLOCKMEMORY_TRACK_ALLOC() ((void)0)
|
||||
#define UTLBLOCKMEMORY_TRACK_FREE() ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlBlockMemory class:
|
||||
// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
class CUtlBlockMemory
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlBlockMemory( int nGrowSize = 0, int nInitSize = 0 );
|
||||
~CUtlBlockMemory();
|
||||
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
void Init( int nGrowSize = 0, int nInitSize = 0 );
|
||||
|
||||
// here to match CUtlMemory, but not used, so it can just return NULL
|
||||
T* Base() { return NULL; }
|
||||
const T* Base() const { return NULL; }
|
||||
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t( I i ) : index( i ) {}
|
||||
I index;
|
||||
|
||||
bool operator==( const Iterator_t it ) const { return index == it.index; }
|
||||
bool operator!=( const Iterator_t it ) const { return index != it.index; }
|
||||
};
|
||||
Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); }
|
||||
Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); }
|
||||
I GetIndex( const Iterator_t &it ) const { return it.index; }
|
||||
bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; }
|
||||
bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
|
||||
|
||||
// element access
|
||||
T& operator[]( I i );
|
||||
const T& operator[]( I i ) const;
|
||||
T& Element( I i );
|
||||
const T& Element( I i ) const;
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( I i ) const;
|
||||
static I InvalidIndex() { return ( I )-1; }
|
||||
|
||||
void Swap( CUtlBlockMemory< T, I > &mem );
|
||||
|
||||
// Size
|
||||
int NumAllocated() const;
|
||||
int Count() const { return NumAllocated(); }
|
||||
|
||||
// Grows memory by max(num,growsize) rounded up to the next power of 2, and returns the allocation index/ptr
|
||||
void Grow( int num = 1 );
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
// Purge all but the given number of elements
|
||||
void Purge( int numElements );
|
||||
|
||||
protected:
|
||||
int Index( int major, int minor ) const { return ( major << m_nIndexShift ) | minor; }
|
||||
int MajorIndex( int i ) const { return i >> m_nIndexShift; }
|
||||
int MinorIndex( int i ) const { return i & m_nIndexMask; }
|
||||
void ChangeSize( int nBlocks );
|
||||
int NumElementsInBlock() const { return m_nIndexMask + 1; }
|
||||
|
||||
T** m_pMemory;
|
||||
int m_nBlocks;
|
||||
int m_nIndexMask : 27;
|
||||
int m_nIndexShift : 5;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T, class I >
|
||||
CUtlBlockMemory<T,I>::CUtlBlockMemory( int nGrowSize, int nInitAllocationCount )
|
||||
: m_pMemory( 0 ), m_nBlocks( 0 ), m_nIndexMask( 0 ), m_nIndexShift( 0 )
|
||||
{
|
||||
Init( nGrowSize, nInitAllocationCount );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
CUtlBlockMemory<T,I>::~CUtlBlockMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fast swap
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Swap( CUtlBlockMemory< T, I > &mem )
|
||||
{
|
||||
V_swap( m_pMemory, mem.m_pMemory );
|
||||
V_swap( m_nBlocks, mem.m_nBlocks );
|
||||
V_swap( m_nIndexMask, mem.m_nIndexMask );
|
||||
V_swap( m_nIndexShift, mem.m_nIndexShift );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
|
||||
{
|
||||
Purge();
|
||||
|
||||
if ( nGrowSize == 0)
|
||||
{
|
||||
// default grow size is smallest size s.t. c++ allocation overhead is ~6% of block size
|
||||
nGrowSize = ( 127 + sizeof( T ) ) / sizeof( T );
|
||||
}
|
||||
nGrowSize = SmallestPowerOfTwoGreaterOrEqual( nGrowSize );
|
||||
m_nIndexMask = nGrowSize - 1;
|
||||
|
||||
m_nIndexShift = 0;
|
||||
while ( nGrowSize > 1 )
|
||||
{
|
||||
nGrowSize >>= 1;
|
||||
++m_nIndexShift;
|
||||
}
|
||||
Assert( m_nIndexMask + 1 == ( 1 << m_nIndexShift ) );
|
||||
|
||||
Grow( nInitSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline T& CUtlBlockMemory<T,I>::operator[]( I i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlBlockMemory<T,I>::operator[]( I i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
const T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline T& CUtlBlockMemory<T,I>::Element( I i )
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
inline const T& CUtlBlockMemory<T,I>::Element( I i ) const
|
||||
{
|
||||
Assert( IsIdxValid(i) );
|
||||
const T *pBlock = m_pMemory[ MajorIndex( i ) ];
|
||||
return pBlock[ MinorIndex( i ) ];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Size
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline int CUtlBlockMemory<T,I>::NumAllocated() const
|
||||
{
|
||||
return m_nBlocks * NumElementsInBlock();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline bool CUtlBlockMemory<T,I>::IsIdxValid( I i ) const
|
||||
{
|
||||
return ( i >= 0 ) && ( MajorIndex( i ) < m_nBlocks );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Grow( int num )
|
||||
{
|
||||
if ( num <= 0 )
|
||||
return;
|
||||
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
int nBlocks = ( num + nBlockSize - 1 ) / nBlockSize;
|
||||
|
||||
ChangeSize( m_nBlocks + nBlocks );
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::ChangeSize( int nBlocks )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE(); // this must stay before the recalculation of m_nBlocks, since it implicitly uses the old value
|
||||
|
||||
int nBlocksOld = m_nBlocks;
|
||||
m_nBlocks = nBlocks;
|
||||
|
||||
UTLBLOCKMEMORY_TRACK_ALLOC(); // this must stay after the recalculation of m_nBlocks, since it implicitly uses the new value
|
||||
|
||||
// free old blocks if shrinking
|
||||
for ( int i = m_nBlocks; i < nBlocksOld; ++i )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory[ i ] );
|
||||
}
|
||||
|
||||
if ( m_pMemory )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory = (T**)realloc( m_pMemory, m_nBlocks * sizeof(T*) );
|
||||
Assert( m_pMemory );
|
||||
}
|
||||
else
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory = (T**)malloc( m_nBlocks * sizeof(T*) );
|
||||
Assert( m_pMemory );
|
||||
}
|
||||
|
||||
if ( !m_pMemory )
|
||||
{
|
||||
//Error( "CUtlBlockMemory overflow!\n" );
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
// allocate new blocks if growing
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
for ( int i = nBlocksOld; i < m_nBlocks; ++i )
|
||||
{
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
m_pMemory[ i ] = (T*)malloc( nBlockSize * sizeof( T ) );
|
||||
Assert( m_pMemory[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we've got at least this much memory
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
inline void CUtlBlockMemory<T,I>::EnsureCapacity( int num )
|
||||
{
|
||||
Grow( num - NumAllocated() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Purge()
|
||||
{
|
||||
if ( !m_pMemory )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < m_nBlocks; ++i )
|
||||
{
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory[ i ] );
|
||||
}
|
||||
m_nBlocks = 0;
|
||||
|
||||
UTLBLOCKMEMORY_TRACK_FREE();
|
||||
free( (void*)m_pMemory );
|
||||
m_pMemory = 0;
|
||||
}
|
||||
|
||||
template< class T, class I >
|
||||
void CUtlBlockMemory<T,I>::Purge( int numElements )
|
||||
{
|
||||
Assert( numElements >= 0 );
|
||||
|
||||
int nAllocated = NumAllocated();
|
||||
if ( numElements > nAllocated )
|
||||
{
|
||||
// Ensure this isn't a grow request in disguise.
|
||||
Assert( numElements <= nAllocated );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( numElements <= 0 )
|
||||
{
|
||||
Purge();
|
||||
return;
|
||||
}
|
||||
|
||||
int nBlockSize = NumElementsInBlock();
|
||||
// int nBlocksOld = m_nBlocks;
|
||||
int nBlocks = ( numElements + nBlockSize - 1 ) / nBlockSize;
|
||||
|
||||
// If the number of blocks is the same as the allocated number of blocks, we are done.
|
||||
if ( nBlocks == m_nBlocks )
|
||||
return;
|
||||
|
||||
ChangeSize( nBlocks );
|
||||
}
|
||||
|
||||
|
||||
#endif // UTLBLOCKMEMORY_H
|
||||
337
csgo2/sdk/tier1/utlfixedmemory.h
Normal file
337
csgo2/sdk/tier1/utlfixedmemory.h
Normal file
@@ -0,0 +1,337 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
// A growable memory class.
|
||||
//===========================================================================//
|
||||
#ifndef UTLFIXEDMEMORY_H
|
||||
#define UTLFIXEDMEMORY_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
#include "../sdk.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4100)
|
||||
#pragma warning (disable:4514)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef UTLFIXEDMEMORY_TRACK
|
||||
#define UTLFIXEDMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#define UTLFIXEDMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 )
|
||||
#else
|
||||
#define UTLFIXEDMEMORY_TRACK_ALLOC() ((void)0)
|
||||
#define UTLFIXEDMEMORY_TRACK_FREE() ((void)0)
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlFixedMemory class:
|
||||
// A growable memory class that allocates non-sequential blocks, but is indexed sequentially
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
class CUtlFixedMemory
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 );
|
||||
~CUtlFixedMemory();
|
||||
|
||||
// Set the size by which the memory grows
|
||||
void Init( int nGrowSize = 0, int nInitSize = 0 );
|
||||
|
||||
// here to match CUtlMemory, but not used, so it can just return NULL
|
||||
T* Base() { return NULL; }
|
||||
const T* Base() const { return NULL; }
|
||||
|
||||
protected:
|
||||
struct BlockHeader_t;
|
||||
|
||||
public:
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {}
|
||||
BlockHeader_t *m_pBlockHeader;
|
||||
intp m_nIndex;
|
||||
|
||||
bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; }
|
||||
bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; }
|
||||
};
|
||||
Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); }
|
||||
Iterator_t Next( const Iterator_t &it ) const
|
||||
{
|
||||
if ( !IsValidIterator( it ) )
|
||||
return InvalidIterator();
|
||||
|
||||
BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader;
|
||||
if ( it.m_nIndex + 1 < pHeader->m_nBlockSize )
|
||||
return Iterator_t( pHeader, it.m_nIndex + 1 );
|
||||
|
||||
return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator();
|
||||
}
|
||||
intp GetIndex( const Iterator_t &it ) const
|
||||
{
|
||||
if ( !IsValidIterator( it ) )
|
||||
return InvalidIndex();
|
||||
|
||||
return ( intp )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex );
|
||||
}
|
||||
bool IsIdxAfter( intp i, const Iterator_t &it ) const
|
||||
{
|
||||
if ( !IsValidIterator( it ) )
|
||||
return false;
|
||||
|
||||
if ( IsInBlock( i, it.m_pBlockHeader ) )
|
||||
return i > GetIndex( it );
|
||||
|
||||
for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext )
|
||||
{
|
||||
if ( IsInBlock( i, pbh ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( NULL, INVALID_INDEX ); }
|
||||
|
||||
// element access
|
||||
T& operator[]( intp i );
|
||||
const T& operator[]( intp i ) const;
|
||||
T& Element( intp i );
|
||||
const T& Element( intp i ) const;
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( intp i ) const;
|
||||
|
||||
// Specify the invalid ('null') index that we'll only return on failure
|
||||
static const intp INVALID_INDEX = 0; // For use with COMPILE_TIME_ASSERT
|
||||
static intp InvalidIndex() { return INVALID_INDEX; }
|
||||
|
||||
// Size
|
||||
int NumAllocated() const;
|
||||
int Count() const { return NumAllocated(); }
|
||||
|
||||
// Grows memory by max(num,growsize), and returns the allocation index/ptr
|
||||
void Grow( int num = 1 );
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num );
|
||||
|
||||
// Memory deallocation
|
||||
void Purge();
|
||||
|
||||
protected:
|
||||
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
|
||||
void Swap( CUtlFixedMemory< T > &mem );
|
||||
|
||||
bool IsInBlock( intp i, BlockHeader_t *pBlockHeader ) const
|
||||
{
|
||||
T *p = ( T* )i;
|
||||
const T *p0 = HeaderToBlock( pBlockHeader );
|
||||
return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize;
|
||||
}
|
||||
|
||||
struct BlockHeader_t
|
||||
{
|
||||
BlockHeader_t *m_pNext;
|
||||
intp m_nBlockSize;
|
||||
};
|
||||
|
||||
const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); }
|
||||
const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; }
|
||||
|
||||
BlockHeader_t* m_pBlocks;
|
||||
int m_nAllocationCount;
|
||||
int m_nGrowSize;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// constructor, destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
template< class T >
|
||||
CUtlFixedMemory<T>::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount )
|
||||
: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 )
|
||||
{
|
||||
Init( nGrowSize, nInitAllocationCount );
|
||||
}
|
||||
|
||||
template< class T >
|
||||
CUtlFixedMemory<T>::~CUtlFixedMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Fast swap - WARNING: Swap invalidates all ptr-based indices!!!
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Swap( CUtlFixedMemory< T > &mem )
|
||||
{
|
||||
V_swap( m_pBlocks, mem.m_pBlocks );
|
||||
V_swap( m_nAllocationCount, mem.m_nAllocationCount );
|
||||
V_swap( m_nGrowSize, mem.m_nGrowSize );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the size by which the memory grows - round up to the next power of 2
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ )
|
||||
{
|
||||
Purge();
|
||||
|
||||
m_nGrowSize = nGrowSize;
|
||||
|
||||
Grow( nInitSize );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// element access
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline T& CUtlFixedMemory<T>::operator[]( intp i )
|
||||
{
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline const T& CUtlFixedMemory<T>::operator[]( intp i ) const
|
||||
{
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline T& CUtlFixedMemory<T>::Element( intp i )
|
||||
{
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline const T& CUtlFixedMemory<T>::Element( intp i ) const
|
||||
{
|
||||
return *( T* )i;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Size
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline int CUtlFixedMemory<T>::NumAllocated() const
|
||||
{
|
||||
return m_nAllocationCount;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is element index valid?
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline bool CUtlFixedMemory<T>::IsIdxValid( intp i ) const
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext )
|
||||
{
|
||||
if ( IsInBlock( i, pbh ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return i != InvalidIndex();
|
||||
#endif
|
||||
}
|
||||
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Grow( int num )
|
||||
{
|
||||
if ( num <= 0 )
|
||||
return;
|
||||
|
||||
int nBlockSize = m_nGrowSize;
|
||||
if ( nBlockSize == 0 )
|
||||
{
|
||||
if ( m_nAllocationCount )
|
||||
{
|
||||
nBlockSize = m_nAllocationCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute an allocation which is at least as big as a cache line...
|
||||
nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T );
|
||||
}
|
||||
}
|
||||
if ( nBlockSize < num )
|
||||
{
|
||||
int n = ( num + nBlockSize -1 ) / nBlockSize;
|
||||
nBlockSize *= n;
|
||||
}
|
||||
m_nAllocationCount += nBlockSize;
|
||||
|
||||
MEM_ALLOC_CREDIT_CLASS();
|
||||
BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) );
|
||||
if ( !pBlockHeader )
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
pBlockHeader->m_pNext = NULL;
|
||||
pBlockHeader->m_nBlockSize = nBlockSize;
|
||||
|
||||
if ( !m_pBlocks )
|
||||
{
|
||||
m_pBlocks = pBlockHeader;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end
|
||||
BlockHeader_t * RESTRICT pbh = m_pBlocks;
|
||||
while ( pbh->m_pNext )
|
||||
{
|
||||
pbh = pbh->m_pNext;
|
||||
}
|
||||
pbh->m_pNext = pBlockHeader;
|
||||
#else
|
||||
pBlockHeader = m_pBlocks;
|
||||
pBlockHeader->m_pNext = m_pBlocks;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes sure we've got at least this much memory
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
inline void CUtlFixedMemory<T>::EnsureCapacity( int num )
|
||||
{
|
||||
Grow( num - NumAllocated() );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memory deallocation
|
||||
//-----------------------------------------------------------------------------
|
||||
template< class T >
|
||||
void CUtlFixedMemory<T>::Purge()
|
||||
{
|
||||
if ( !m_pBlocks )
|
||||
return;
|
||||
|
||||
for ( BlockHeader_t *pbh = m_pBlocks; pbh; )
|
||||
{
|
||||
BlockHeader_t *pFree = pbh;
|
||||
pbh = pbh->m_pNext;
|
||||
free( pFree );
|
||||
}
|
||||
m_pBlocks = NULL;
|
||||
m_nAllocationCount = 0;
|
||||
}
|
||||
|
||||
#endif // UTLFIXEDMEMORY_H
|
||||
Reference in New Issue
Block a user