mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
dcf515fea8
* Prepare for 64bits * Add the dynamic and static librairies * Delete choreoobjects_x86_64.a --------- Co-authored-by: Kenzzer <kenzzer@users.noreply.github.com>
407 lines
10 KiB
C++
407 lines
10 KiB
C++
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose:
|
||
//
|
||
// $NoKeywords: $
|
||
//
|
||
//=============================================================================//
|
||
|
||
#include "basetypes.h"
|
||
#include "datamanager.h"
|
||
|
||
#define AUTO_LOCK_DM() AUTO_LOCK_( CDataManagerBase, *this )
|
||
|
||
CDataManagerBase::CDataManagerBase( unsigned int maxSize )
|
||
{
|
||
m_targetMemorySize = maxSize;
|
||
m_memUsed = 0;
|
||
m_lruList = m_memoryLists.CreateList();
|
||
m_lockList = m_memoryLists.CreateList();
|
||
m_freeList = m_memoryLists.CreateList();
|
||
m_listsAreFreed = 0;
|
||
}
|
||
|
||
CDataManagerBase::~CDataManagerBase()
|
||
{
|
||
Assert( m_listsAreFreed );
|
||
}
|
||
|
||
void CDataManagerBase::NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize )
|
||
{
|
||
Lock();
|
||
m_memUsed += (int)newSize - (int)oldSize;
|
||
Unlock();
|
||
}
|
||
|
||
void CDataManagerBase::SetTargetSize( unsigned int targetSize )
|
||
{
|
||
m_targetMemorySize = targetSize;
|
||
}
|
||
|
||
unsigned int CDataManagerBase::FlushAllUnlocked()
|
||
{
|
||
Lock();
|
||
|
||
int nFlush = m_memoryLists.Count( m_lruList );
|
||
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
|
||
CUtlVector<void *> destroyList( pScratch, nFlush );
|
||
|
||
unsigned nBytesInitial = MemUsed_Inline();
|
||
|
||
int node = m_memoryLists.Head(m_lruList);
|
||
while ( node != m_memoryLists.InvalidIndex() )
|
||
{
|
||
int next = m_memoryLists.Next(node);
|
||
m_memoryLists.Unlink( m_lruList, node );
|
||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||
node = next;
|
||
}
|
||
|
||
Unlock();
|
||
|
||
for ( int i = 0; i < nFlush; i++ )
|
||
{
|
||
DestroyResourceStorage( destroyList[i] );
|
||
}
|
||
|
||
return ( nBytesInitial - MemUsed_Inline() );
|
||
}
|
||
|
||
unsigned int CDataManagerBase::FlushToTargetSize()
|
||
{
|
||
return EnsureCapacity(0);
|
||
}
|
||
|
||
// Frees everything! The LRU AND the LOCKED items. This is only used to forcibly free the resources,
|
||
// not to make space.
|
||
|
||
unsigned int CDataManagerBase::FlushAll()
|
||
{
|
||
Lock();
|
||
|
||
int nFlush = m_memoryLists.Count( m_lruList ) + m_memoryLists.Count( m_lockList );
|
||
void **pScratch = (void **)_alloca( nFlush * sizeof(void *) );
|
||
CUtlVector<void *> destroyList( pScratch, nFlush );
|
||
|
||
unsigned result = MemUsed_Inline();
|
||
int node;
|
||
int nextNode;
|
||
|
||
node = m_memoryLists.Head(m_lruList);
|
||
while ( node != m_memoryLists.InvalidIndex() )
|
||
{
|
||
nextNode = m_memoryLists.Next(node);
|
||
m_memoryLists.Unlink( m_lruList, node );
|
||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||
node = nextNode;
|
||
}
|
||
|
||
node = m_memoryLists.Head(m_lockList);
|
||
while ( node != m_memoryLists.InvalidIndex() )
|
||
{
|
||
nextNode = m_memoryLists.Next(node);
|
||
m_memoryLists.Unlink( m_lockList, node );
|
||
m_memoryLists[node].lockCount = 0;
|
||
destroyList.AddToTail( GetForFreeByIndex( node ) );
|
||
node = nextNode;
|
||
}
|
||
|
||
m_listsAreFreed = false;
|
||
Unlock();
|
||
|
||
for ( int i = 0; i < nFlush; i++ )
|
||
{
|
||
DestroyResourceStorage( destroyList[i] );
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
unsigned int CDataManagerBase::Purge( unsigned int nBytesToPurge )
|
||
{
|
||
unsigned int nTargetSize = MemUsed_Inline() - nBytesToPurge;
|
||
unsigned int nImpliedCapacity = MemTotal_Inline() - nTargetSize;
|
||
return EnsureCapacity( nImpliedCapacity );
|
||
}
|
||
|
||
|
||
void CDataManagerBase::DestroyResource( memhandle_t handle )
|
||
{
|
||
Lock();
|
||
unsigned short index = FromHandle( handle );
|
||
if ( !m_memoryLists.IsValidIndex(index) )
|
||
{
|
||
Unlock();
|
||
return;
|
||
}
|
||
|
||
Assert( m_memoryLists[index].lockCount == 0 );
|
||
if ( m_memoryLists[index].lockCount )
|
||
BreakLock( handle );
|
||
m_memoryLists.Unlink( m_lruList, index );
|
||
void *p = GetForFreeByIndex( index );
|
||
Unlock();
|
||
|
||
DestroyResourceStorage( p );
|
||
}
|
||
|
||
|
||
void *CDataManagerBase::LockResource( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||
{
|
||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||
m_memoryLists.LinkToTail( m_lockList, memoryIndex );
|
||
}
|
||
Assert(m_memoryLists[memoryIndex].lockCount != (unsigned short)-1);
|
||
m_memoryLists[memoryIndex].lockCount++;
|
||
return m_memoryLists[memoryIndex].pStore;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
int CDataManagerBase::UnlockResource( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
Assert( m_memoryLists[memoryIndex].lockCount > 0 );
|
||
if ( m_memoryLists[memoryIndex].lockCount > 0 )
|
||
{
|
||
m_memoryLists[memoryIndex].lockCount--;
|
||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||
{
|
||
m_memoryLists.Unlink( m_lockList, memoryIndex );
|
||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||
}
|
||
}
|
||
return m_memoryLists[memoryIndex].lockCount;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void *CDataManagerBase::GetResource_NoLockNoLRUTouch( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
return m_memoryLists[memoryIndex].pStore;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
|
||
void *CDataManagerBase::GetResource_NoLock( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
TouchByIndex( memoryIndex );
|
||
return m_memoryLists[memoryIndex].pStore;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
void CDataManagerBase::TouchResource( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
TouchByIndex( FromHandle(handle) );
|
||
}
|
||
|
||
void CDataManagerBase::MarkAsStale( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||
{
|
||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||
m_memoryLists.LinkToHead( m_lruList, memoryIndex );
|
||
}
|
||
}
|
||
}
|
||
|
||
int CDataManagerBase::BreakLock( memhandle_t handle )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
unsigned short memoryIndex = FromHandle(handle);
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() && m_memoryLists[memoryIndex].lockCount )
|
||
{
|
||
int nBroken = m_memoryLists[memoryIndex].lockCount;
|
||
m_memoryLists[memoryIndex].lockCount = 0;
|
||
m_memoryLists.Unlink( m_lockList, memoryIndex );
|
||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||
|
||
return nBroken;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int CDataManagerBase::BreakAllLocks()
|
||
{
|
||
AUTO_LOCK_DM();
|
||
int nBroken = 0;
|
||
int node;
|
||
int nextNode;
|
||
|
||
node = m_memoryLists.Head(m_lockList);
|
||
while ( node != m_memoryLists.InvalidIndex() )
|
||
{
|
||
nBroken++;
|
||
nextNode = m_memoryLists.Next(node);
|
||
m_memoryLists[node].lockCount = 0;
|
||
m_memoryLists.Unlink( m_lockList, node );
|
||
m_memoryLists.LinkToTail( m_lruList, node );
|
||
node = nextNode;
|
||
}
|
||
|
||
return nBroken;
|
||
|
||
}
|
||
|
||
unsigned short CDataManagerBase::CreateHandle( bool bCreateLocked )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
int memoryIndex = m_memoryLists.Head(m_freeList);
|
||
unsigned short list = ( bCreateLocked ) ? m_lockList : m_lruList;
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
m_memoryLists.Unlink( m_freeList, memoryIndex );
|
||
m_memoryLists.LinkToTail( list, memoryIndex );
|
||
}
|
||
else
|
||
{
|
||
memoryIndex = m_memoryLists.AddToTail( list );
|
||
}
|
||
|
||
if ( bCreateLocked )
|
||
{
|
||
m_memoryLists[memoryIndex].lockCount++;
|
||
}
|
||
|
||
return memoryIndex;
|
||
}
|
||
|
||
memhandle_t CDataManagerBase::StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize )
|
||
{
|
||
AUTO_LOCK_DM();
|
||
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
|
||
mem.pStore = pStore;
|
||
m_memUsed += realSize;
|
||
return ToHandle(memoryIndex);
|
||
}
|
||
|
||
void CDataManagerBase::TouchByIndex( unsigned short memoryIndex )
|
||
{
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
if ( m_memoryLists[memoryIndex].lockCount == 0 )
|
||
{
|
||
m_memoryLists.Unlink( m_lruList, memoryIndex );
|
||
m_memoryLists.LinkToTail( m_lruList, memoryIndex );
|
||
}
|
||
}
|
||
}
|
||
|
||
memhandle_t CDataManagerBase::ToHandle( unsigned short index )
|
||
{
|
||
unsigned int hiword = m_memoryLists.Element(index).serial;
|
||
hiword <<= 16;
|
||
index++;
|
||
return memhandle_t::MakeHandle( hiword|index );
|
||
}
|
||
|
||
unsigned int CDataManagerBase::TargetSize()
|
||
{
|
||
return MemTotal_Inline();
|
||
}
|
||
|
||
unsigned int CDataManagerBase::AvailableSize()
|
||
{
|
||
return MemAvailable_Inline();
|
||
}
|
||
|
||
|
||
unsigned int CDataManagerBase::UsedSize()
|
||
{
|
||
return MemUsed_Inline();
|
||
}
|
||
|
||
// free resources until there is enough space to hold "size"
|
||
unsigned int CDataManagerBase::EnsureCapacity( unsigned int size )
|
||
{
|
||
unsigned nBytesInitial = MemUsed_Inline();
|
||
while ( MemUsed_Inline() > MemTotal_Inline() || MemAvailable_Inline() < size )
|
||
{
|
||
Lock();
|
||
int lruIndex = m_memoryLists.Head( m_lruList );
|
||
if ( lruIndex == m_memoryLists.InvalidIndex() )
|
||
{
|
||
Unlock();
|
||
break;
|
||
}
|
||
m_memoryLists.Unlink( m_lruList, lruIndex );
|
||
void *p = GetForFreeByIndex( lruIndex );
|
||
Unlock();
|
||
DestroyResourceStorage( p );
|
||
}
|
||
return ( nBytesInitial - MemUsed_Inline() );
|
||
}
|
||
|
||
// free this resource and move the handle to the free list
|
||
void *CDataManagerBase::GetForFreeByIndex( unsigned short memoryIndex )
|
||
{
|
||
void *p = NULL;
|
||
if ( memoryIndex != m_memoryLists.InvalidIndex() )
|
||
{
|
||
Assert( m_memoryLists[memoryIndex].lockCount == 0 );
|
||
|
||
resource_lru_element_t &mem = m_memoryLists[memoryIndex];
|
||
unsigned size = GetRealSize( mem.pStore );
|
||
if ( size > m_memUsed )
|
||
{
|
||
ExecuteOnce( Warning( "Data manager 'used' memory incorrect\n" ) );
|
||
size = m_memUsed;
|
||
}
|
||
m_memUsed -= size;
|
||
p = mem.pStore;
|
||
mem.pStore = NULL;
|
||
mem.serial++;
|
||
m_memoryLists.LinkToTail( m_freeList, memoryIndex );
|
||
}
|
||
return p;
|
||
}
|
||
|
||
// get a list of everything in the LRU
|
||
void CDataManagerBase::GetLRUHandleList( CUtlVector< memhandle_t >& list )
|
||
{
|
||
for ( int node = m_memoryLists.Tail(m_lruList);
|
||
node != m_memoryLists.InvalidIndex();
|
||
node = m_memoryLists.Previous(node) )
|
||
{
|
||
list.AddToTail( ToHandle( node ) );
|
||
}
|
||
}
|
||
|
||
// get a list of everything locked
|
||
void CDataManagerBase::GetLockHandleList( CUtlVector< memhandle_t >& list )
|
||
{
|
||
for ( int node = m_memoryLists.Head(m_lockList);
|
||
node != m_memoryLists.InvalidIndex();
|
||
node = m_memoryLists.Next(node) )
|
||
{
|
||
list.AddToTail( ToHandle( node ) );
|
||
}
|
||
}
|
||
|