uid issue
This commit is contained in:
391
datacache/datacache.h
Normal file
391
datacache/datacache.h
Normal file
@ -0,0 +1,391 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef DATACACHE_H
|
||||
#define DATACACHE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "datamanager.h"
|
||||
#include "utlhash.h"
|
||||
#include "mempool.h"
|
||||
#include "tier0/tslist.h"
|
||||
#include "datacache_common.h"
|
||||
#include "tier3/tier3.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Data Cache class declarations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDataCache;
|
||||
class CDataCacheSection;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct DataCacheItemData_t
|
||||
{
|
||||
const void * pItemData;
|
||||
unsigned size;
|
||||
DataCacheClientID_t clientId;
|
||||
CDataCacheSection * pSection;
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
#define DC_NO_NEXT_LOCKED ((DataCacheItem_t *)-1)
|
||||
#define DC_MAX_THREADS_FRAMELOCKED 6
|
||||
|
||||
|
||||
struct DataCacheItem_t : DataCacheItemData_t
|
||||
{
|
||||
DataCacheItem_t( const DataCacheItemData_t &data )
|
||||
: DataCacheItemData_t( data ),
|
||||
hLRU( INVALID_MEMHANDLE )
|
||||
{
|
||||
memset( pNextFrameLocked, 0xff, sizeof(pNextFrameLocked) );
|
||||
}
|
||||
|
||||
static DataCacheItem_t *CreateResource( const DataCacheItemData_t &data ) { return new DataCacheItem_t(data); }
|
||||
static unsigned int EstimatedSize( const DataCacheItemData_t &data ) { return data.size; }
|
||||
void DestroyResource();
|
||||
DataCacheItem_t *GetData() { return this; }
|
||||
unsigned int Size() { return size; }
|
||||
|
||||
memhandle_t hLRU;
|
||||
DataCacheItem_t *pNextFrameLocked[DC_MAX_THREADS_FRAMELOCKED];
|
||||
|
||||
DECLARE_FIXEDSIZE_ALLOCATOR_MT(DataCacheItem_t);
|
||||
};
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
typedef CDataManager<DataCacheItem_t, DataCacheItemData_t, DataCacheItem_t *, CThreadFastMutex> CDataCacheLRU;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CDataCacheSection
|
||||
//
|
||||
// Purpose: Implements a sub-section of the global cache. Subsections are
|
||||
// areas of the cache with thier own memory constraints and common
|
||||
// management.
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDataCacheSection : public IDataCacheSection
|
||||
{
|
||||
public:
|
||||
CDataCacheSection( CDataCache *pSharedCache, IDataCacheClient *pClient, const char *pszName );
|
||||
~CDataCacheSection();
|
||||
|
||||
IDataCache *GetSharedCache();
|
||||
IDataCacheClient *GetClient() { return m_pClient; }
|
||||
const char *GetName() { return szName; }
|
||||
|
||||
//--------------------------------------------------------
|
||||
// IDataCacheSection methods
|
||||
//--------------------------------------------------------
|
||||
virtual void SetLimits( const DataCacheLimits_t &limits );
|
||||
const DataCacheLimits_t &GetLimits();
|
||||
virtual void SetOptions( unsigned options );
|
||||
virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL );
|
||||
|
||||
inline unsigned GetNumBytes() { return m_status.nBytes; }
|
||||
inline unsigned GetNumItems() { return m_status.nItems; }
|
||||
|
||||
inline unsigned GetNumBytesLocked() { return m_status.nBytesLocked; }
|
||||
inline unsigned GetNumItemsLocked() { return m_status.nItemsLocked; }
|
||||
|
||||
inline unsigned GetNumBytesUnlocked() { return m_status.nBytes - m_status.nBytesLocked; }
|
||||
inline unsigned GetNumItemsUnlocked() { return m_status.nItems - m_status.nItemsLocked; }
|
||||
|
||||
virtual void EnsureCapacity( unsigned nBytes, unsigned nItems = 1 );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual bool Add( DataCacheClientID_t clientId, const void *pItemData, unsigned size, DataCacheHandle_t *pHandle );
|
||||
virtual bool AddEx( DataCacheClientID_t clientId, const void *pItemData, unsigned size, unsigned flags, DataCacheHandle_t *pHandle );
|
||||
virtual DataCacheHandle_t Find( DataCacheClientID_t clientId );
|
||||
virtual DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, const void **ppItemData = NULL, unsigned *pItemSize = NULL, bool bNotify = false );
|
||||
virtual bool IsPresent( DataCacheHandle_t handle );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual void *Lock( DataCacheHandle_t handle );
|
||||
virtual int Unlock( DataCacheHandle_t handle );
|
||||
virtual void *Get( DataCacheHandle_t handle, bool bFrameLock = false );
|
||||
virtual void *GetNoTouch( DataCacheHandle_t handle, bool bFrameLock = false );
|
||||
virtual void GetAndLockMultiple( void **ppData, int nCount, DataCacheHandle_t *pHandles );
|
||||
virtual void LockMutex();
|
||||
virtual void UnlockMutex();
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual int BeginFrameLocking();
|
||||
virtual bool IsFrameLocking();
|
||||
virtual void *FrameLock( DataCacheHandle_t handle );
|
||||
virtual int EndFrameLocking();
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual int GetLockCount( DataCacheHandle_t handle );
|
||||
virtual int BreakLock( DataCacheHandle_t handle );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual int *GetFrameUnlockCounterPtr();
|
||||
int m_nFrameUnlockCounter;
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual bool Touch( DataCacheHandle_t handle );
|
||||
virtual bool Age( DataCacheHandle_t handle );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true );
|
||||
virtual unsigned Purge( unsigned nBytes );
|
||||
unsigned PurgeItems( unsigned nItems );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT );
|
||||
|
||||
virtual void UpdateSize( DataCacheHandle_t handle, unsigned int nNewSize );
|
||||
|
||||
virtual unsigned int GetOptions();
|
||||
|
||||
private:
|
||||
friend void DataCacheItem_t::DestroyResource();
|
||||
|
||||
virtual void OnAdd( DataCacheClientID_t clientId, DataCacheHandle_t hCacheItem ) {}
|
||||
virtual DataCacheHandle_t DoFind( DataCacheClientID_t clientId );
|
||||
virtual void OnRemove( DataCacheClientID_t clientId ) {}
|
||||
|
||||
memhandle_t GetFirstUnlockedItem();
|
||||
memhandle_t GetFirstLockedItem();
|
||||
memhandle_t GetNextItem( memhandle_t );
|
||||
DataCacheItem_t *AccessItem( memhandle_t hCurrent );
|
||||
bool DiscardItem( memhandle_t hItem, DataCacheNotificationType_t type );
|
||||
bool DiscardItemData( DataCacheItem_t *pItem, DataCacheNotificationType_t type );
|
||||
void NoteAdd( int size );
|
||||
void NoteRemove( int size );
|
||||
void NoteLock( int size );
|
||||
void NoteUnlock( int size );
|
||||
void NoteSizeChanged( int oldSize, int newSize );
|
||||
|
||||
// for debugging only, under user cvar enabling, causes datacache stress flushing
|
||||
void ForceFlushDebug( bool bFlush );
|
||||
|
||||
struct FrameLock_t
|
||||
{
|
||||
int m_iLock;
|
||||
DataCacheItem_t *m_pFirst;
|
||||
int m_iThread;
|
||||
};
|
||||
//typedef CThreadLocal<FrameLock_t *> CThreadFrameLock;
|
||||
|
||||
CDataCacheLRU & m_LRU;
|
||||
FrameLock_t * m_FrameLocks[MAX_THREADS_SUPPORTED];
|
||||
DataCacheStatus_t m_status;
|
||||
DataCacheLimits_t m_limits;
|
||||
IDataCacheClient * m_pClient;
|
||||
unsigned m_options;
|
||||
CDataCache * m_pSharedCache;
|
||||
char szName[DC_MAX_CLIENT_NAME + 1];
|
||||
CTSSimpleList<FrameLock_t> m_FreeFrameLocks;
|
||||
|
||||
protected:
|
||||
CThreadFastMutex & m_mutex;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CDataCacheSectionFastFind
|
||||
//
|
||||
// Purpose: A section variant that allows clients to have cache support tracking
|
||||
// efficiently (a true cache, not just an LRU)
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDataCacheSectionFastFind : public CDataCacheSection
|
||||
{
|
||||
public:
|
||||
CDataCacheSectionFastFind(CDataCache *pSharedCache, IDataCacheClient *pClient, const char *pszName )
|
||||
: CDataCacheSection( pSharedCache, pClient, pszName )
|
||||
{
|
||||
m_Handles.Init( 1024 );
|
||||
}
|
||||
|
||||
private:
|
||||
virtual DataCacheHandle_t DoFind( DataCacheClientID_t clientId );
|
||||
virtual void OnAdd( DataCacheClientID_t clientId, DataCacheHandle_t hCacheItem );
|
||||
virtual void OnRemove( DataCacheClientID_t clientId );
|
||||
|
||||
CUtlHashFast<DataCacheHandle_t> m_Handles;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CDataCache
|
||||
//
|
||||
// Purpose: The global shared cache. Manages sections and overall budgets.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDataCache : public CTier3AppSystem< IDataCache >
|
||||
{
|
||||
typedef CTier3AppSystem< IDataCache > BaseClass;
|
||||
|
||||
public:
|
||||
CDataCache();
|
||||
|
||||
//--------------------------------------------------------
|
||||
// IAppSystem methods
|
||||
//--------------------------------------------------------
|
||||
virtual bool Connect( CreateInterfaceFn factory );
|
||||
virtual void Disconnect();
|
||||
virtual void *QueryInterface( const char *pInterfaceName );
|
||||
virtual InitReturnVal_t Init();
|
||||
virtual void Shutdown();
|
||||
|
||||
//--------------------------------------------------------
|
||||
// IDataCache methods
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual void SetSize( int nMaxBytes );
|
||||
virtual void SetOptions( unsigned options );
|
||||
virtual void SetSectionLimits( const char *pszSectionName, const DataCacheLimits_t &limits );
|
||||
virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual IDataCacheSection *AddSection( IDataCacheClient *pClient, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false );
|
||||
virtual void RemoveSection( const char *pszClientName, bool bCallFlush = true );
|
||||
virtual IDataCacheSection *FindSection( const char *pszClientName );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
void EnsureCapacity( unsigned nBytes );
|
||||
virtual unsigned Purge( unsigned nBytes );
|
||||
virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT, const char *pszSection = NULL );
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
||||
inline unsigned GetNumBytes() { return m_status.nBytes; }
|
||||
inline unsigned GetNumItems() { return m_status.nItems; }
|
||||
|
||||
inline unsigned GetNumBytesLocked() { return m_status.nBytesLocked; }
|
||||
inline unsigned GetNumItemsLocked() { return m_status.nItemsLocked; }
|
||||
|
||||
inline unsigned GetNumBytesUnlocked() { return m_status.nBytes - m_status.nBytesLocked; }
|
||||
inline unsigned GetNumItemsUnlocked() { return m_status.nItems - m_status.nItemsLocked; }
|
||||
|
||||
virtual int GetSectionCount( void );
|
||||
virtual const char *GetSectionName( int iIndex );
|
||||
|
||||
private:
|
||||
//-----------------------------------------------------
|
||||
|
||||
friend class CDataCacheSection;
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
DataCacheItem_t *AccessItem( memhandle_t hCurrent );
|
||||
|
||||
bool IsInFlush() { return m_bInFlush; }
|
||||
int FindSectionIndex( const char *pszSection );
|
||||
|
||||
// Utilities used by the data cache report
|
||||
void OutputItemReport( memhandle_t hItem, void *pXboxData = NULL );
|
||||
static bool SortMemhandlesBySizeLessFunc( const memhandle_t& lhs, const memhandle_t& rhs );
|
||||
|
||||
//-----------------------------------------------------
|
||||
|
||||
CDataCacheLRU m_LRU;
|
||||
DataCacheStatus_t m_status;
|
||||
CUtlVector<CDataCacheSection *> m_Sections;
|
||||
bool m_bInFlush;
|
||||
CThreadFastMutex & m_mutex;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
extern CDataCache g_DataCache;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline DataCacheItem_t *CDataCache::AccessItem( memhandle_t hCurrent )
|
||||
{
|
||||
return m_LRU.GetResource_NoLockNoLRUTouch( hCurrent );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline IDataCache *CDataCacheSection::GetSharedCache()
|
||||
{
|
||||
return m_pSharedCache;
|
||||
}
|
||||
|
||||
inline DataCacheItem_t *CDataCacheSection::AccessItem( memhandle_t hCurrent )
|
||||
{
|
||||
return m_pSharedCache->AccessItem( hCurrent );
|
||||
}
|
||||
|
||||
// Note: if status updates are moved out of a mutexed section, will need to change these to use interlocked instructions
|
||||
|
||||
inline void CDataCacheSection::NoteSizeChanged( int oldSize, int newSize )
|
||||
{
|
||||
int nBytes = ( newSize - oldSize );
|
||||
|
||||
m_status.nBytes += nBytes;
|
||||
m_status.nBytesLocked += nBytes;
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytes, nBytes );
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytesLocked, nBytes );
|
||||
}
|
||||
|
||||
inline void CDataCacheSection::NoteAdd( int size )
|
||||
{
|
||||
m_status.nBytes += size;
|
||||
m_status.nItems++;
|
||||
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytes, size );
|
||||
ThreadInterlockedIncrement( &m_pSharedCache->m_status.nItems );
|
||||
}
|
||||
|
||||
inline void CDataCacheSection::NoteRemove( int size )
|
||||
{
|
||||
m_status.nBytes -= size;
|
||||
m_status.nItems--;
|
||||
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytes, -size );
|
||||
ThreadInterlockedDecrement( &m_pSharedCache->m_status.nItems );
|
||||
}
|
||||
|
||||
inline void CDataCacheSection::NoteLock( int size )
|
||||
{
|
||||
m_status.nBytesLocked += size;
|
||||
m_status.nItemsLocked++;
|
||||
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytesLocked, size );
|
||||
ThreadInterlockedIncrement( &m_pSharedCache->m_status.nItemsLocked );
|
||||
}
|
||||
|
||||
inline void CDataCacheSection::NoteUnlock( int size )
|
||||
{
|
||||
m_status.nBytesLocked -= size;
|
||||
m_status.nItemsLocked--;
|
||||
|
||||
ThreadInterlockedExchangeAdd( &m_pSharedCache->m_status.nBytesLocked, -size );
|
||||
ThreadInterlockedDecrement( &m_pSharedCache->m_status.nItemsLocked );
|
||||
|
||||
// something has been unlocked, assume cached pointers are now invalid
|
||||
m_nFrameUnlockCounter++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif // DATACACHE_H
|
Reference in New Issue
Block a user