diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /datacache/datacache.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'datacache/datacache.h')
| -rw-r--r-- | datacache/datacache.h | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/datacache/datacache.h b/datacache/datacache.h new file mode 100644 index 0000000..56b7710 --- /dev/null +++ b/datacache/datacache.h @@ -0,0 +1,384 @@ +//========= Copyright 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 *)0xffffffff) +#define DC_MAX_THREADS_FRAMELOCKED 4 + +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 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 ); + +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 ); + + struct FrameLock_t + { + //$ WARNING: This needs a TSLNodeBase_t as the first item in here. + TSLNodeBase_t base; + int m_iLock; + DataCacheItem_t *m_pFirst; + int m_iThread; + }; + typedef CThreadLocal<FrameLock_t *> CThreadFrameLock; + + CDataCacheLRU & m_LRU; + CThreadFrameLock m_ThreadFrameLock; + 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; } + +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 ); + 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
\ No newline at end of file |