mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-12 03:39:10 +00:00
1
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: A fast stack memory allocator that uses virtual memory if available
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef MEMSTACK_H
|
||||
#define MEMSTACK_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef unsigned MemoryStackMark_t;
|
||||
|
||||
class CMemoryStack
|
||||
{
|
||||
public:
|
||||
CMemoryStack();
|
||||
~CMemoryStack();
|
||||
|
||||
bool Init( unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 );
|
||||
#ifdef _X360
|
||||
bool InitPhysical( unsigned size = 0, unsigned alignment = 16 );
|
||||
#endif
|
||||
void Term();
|
||||
|
||||
int GetSize();
|
||||
int GetMaxSize();
|
||||
int GetUsed();
|
||||
|
||||
void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT;
|
||||
|
||||
MemoryStackMark_t GetCurrentAllocPoint();
|
||||
void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true );
|
||||
void FreeAll( bool bDecommit = true );
|
||||
|
||||
void Access( void **ppRegion, unsigned *pBytes );
|
||||
|
||||
void PrintContents();
|
||||
|
||||
void *GetBase();
|
||||
const void *GetBase() const { return const_cast<CMemoryStack *>(this)->GetBase(); }
|
||||
|
||||
private:
|
||||
bool CommitTo( byte * ) RESTRICT;
|
||||
|
||||
byte *m_pNextAlloc;
|
||||
byte *m_pCommitLimit;
|
||||
byte *m_pAllocLimit;
|
||||
|
||||
byte *m_pBase;
|
||||
|
||||
unsigned m_maxSize;
|
||||
unsigned m_alignment;
|
||||
#ifdef _WIN32
|
||||
unsigned m_commitSize;
|
||||
unsigned m_minCommit;
|
||||
#endif
|
||||
#ifdef _X360
|
||||
bool m_bPhysical;
|
||||
#endif
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT
|
||||
{
|
||||
Assert( m_pBase );
|
||||
|
||||
int alignment = m_alignment;
|
||||
if ( bytes )
|
||||
{
|
||||
bytes = AlignValue( bytes, alignment );
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes = alignment;
|
||||
}
|
||||
|
||||
|
||||
void *pResult = m_pNextAlloc;
|
||||
byte *pNextAlloc = m_pNextAlloc + bytes;
|
||||
|
||||
if ( pNextAlloc > m_pCommitLimit )
|
||||
{
|
||||
if ( !CommitTo( pNextAlloc ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bClear )
|
||||
{
|
||||
memset( pResult, 0, bytes );
|
||||
}
|
||||
|
||||
m_pNextAlloc = pNextAlloc;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline int CMemoryStack::GetMaxSize()
|
||||
{
|
||||
return m_maxSize;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline int CMemoryStack::GetUsed()
|
||||
{
|
||||
return ( m_pNextAlloc - m_pBase );
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline void *CMemoryStack::GetBase()
|
||||
{
|
||||
return m_pBase;
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint()
|
||||
{
|
||||
return ( m_pNextAlloc - m_pBase );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The CUtlMemoryStack class:
|
||||
// A fixed memory class
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 >
|
||||
class CUtlMemoryStack
|
||||
{
|
||||
public:
|
||||
// constructor, destructor
|
||||
CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); }
|
||||
CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
|
||||
// Can we use this index?
|
||||
bool IsIdxValid( I i ) const { return (i >= 0) && (i < m_nAllocated); }
|
||||
|
||||
// Specify the invalid ('null') index that we'll only return on failure
|
||||
static const I INVALID_INDEX = ( I )-1; // For use with COMPILE_TIME_ASSERT
|
||||
static I InvalidIndex() { return INVALID_INDEX; }
|
||||
|
||||
class Iterator_t
|
||||
{
|
||||
Iterator_t( I i ) : index( i ) {}
|
||||
I index;
|
||||
friend class CUtlMemoryStack<T,I,MAX_SIZE, COMMIT_SIZE, INITIAL_COMMIT>;
|
||||
public:
|
||||
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( m_nAllocated ? 0 : InvalidIndex() ); }
|
||||
Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? 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 it.index >= 0 && it.index < m_nAllocated; }
|
||||
Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); }
|
||||
|
||||
// Gets the base address
|
||||
T* Base() { return (T*)m_MemoryStack.GetBase(); }
|
||||
const T* Base() const { return (const T*)m_MemoryStack.GetBase(); }
|
||||
|
||||
// element access
|
||||
T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; }
|
||||
|
||||
// Attaches the buffer to external memory....
|
||||
void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); }
|
||||
|
||||
// Size
|
||||
int NumAllocated() const { return m_nAllocated; }
|
||||
int Count() const { return m_nAllocated; }
|
||||
|
||||
// Grows the memory, so that at least allocated + num elements are allocated
|
||||
void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); }
|
||||
|
||||
// Makes sure we've got at least this much memory
|
||||
void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); }
|
||||
|
||||
// Memory deallocation
|
||||
void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; }
|
||||
|
||||
// is the memory externally allocated?
|
||||
bool IsExternallyAllocated() const { return false; }
|
||||
|
||||
// Set the size by which the memory grows
|
||||
void SetGrowSize( int size ) {}
|
||||
|
||||
private:
|
||||
CMemoryStack m_MemoryStack;
|
||||
int m_nAllocated;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // MEMSTACK_H
|
||||
Reference in New Issue
Block a user