summaryrefslogtreecommitdiff
path: root/datacache/datacache.h
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /datacache/datacache.h
downloadarchived-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.h384
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