diff options
Diffstat (limited to 'public/datacache/idatacache.h')
| -rw-r--r-- | public/datacache/idatacache.h | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/public/datacache/idatacache.h b/public/datacache/idatacache.h new file mode 100644 index 0000000..c21937f --- /dev/null +++ b/public/datacache/idatacache.h @@ -0,0 +1,545 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef IDATACACHE_H +#define IDATACACHE_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "tier0/dbg.h" +#include "appframework/IAppSystem.h" + +class IDataCache; + +//----------------------------------------------------------------------------- +// +// Shared Data Cache API +// +//----------------------------------------------------------------------------- + +#define DATACACHE_INTERFACE_VERSION "VDataCache003" + +//----------------------------------------------------------------------------- +// Support types and enums +//----------------------------------------------------------------------------- + +//--------------------------------------------------------- +// Unique (per section) identifier for a cache item defined by client +//--------------------------------------------------------- +typedef uint32 DataCacheClientID_t; + + +//--------------------------------------------------------- +// Cache-defined handle for a cache item +//--------------------------------------------------------- +FORWARD_DECLARE_HANDLE( memhandle_t ); +typedef memhandle_t DataCacheHandle_t; +#define DC_INVALID_HANDLE ((DataCacheHandle_t)0) + +//--------------------------------------------------------- +// Cache Limits +//--------------------------------------------------------- +struct DataCacheLimits_t +{ + DataCacheLimits_t( unsigned _nMaxBytes = (unsigned)-1, unsigned _nMaxItems = (unsigned)-1, unsigned _nMinBytes = 0, unsigned _nMinItems = 0 ) + : nMaxBytes(_nMaxBytes), + nMaxItems(_nMaxItems), + nMinBytes(_nMinBytes), + nMinItems(_nMinItems) + { + } + + // Maximum levels permitted + unsigned nMaxBytes; + unsigned nMaxItems; + + // Minimum levels permitted + unsigned nMinBytes; + unsigned nMinItems; +}; + +//--------------------------------------------------------- +// Cache status +//--------------------------------------------------------- +struct DataCacheStatus_t +{ + // Current state of the cache + unsigned nBytes; + unsigned nItems; + + unsigned nBytesLocked; + unsigned nItemsLocked; + + // Diagnostics + unsigned nFindRequests; + unsigned nFindHits; +}; + +//--------------------------------------------------------- +// Cache options +//--------------------------------------------------------- +enum DataCacheOptions_t +{ + DC_TRACE_ACTIVITY = (1 << 0), + DC_FORCE_RELOCATE = (1 << 1), + DC_ALWAYS_MISS = (1 << 2), + DC_VALIDATE = (1 << 3), +}; + + +//--------------------------------------------------------- +// Cache report types +//--------------------------------------------------------- +enum DataCacheReportType_t +{ + DC_SUMMARY_REPORT, + DC_DETAIL_REPORT, + DC_DETAIL_REPORT_LRU, +}; + + +//--------------------------------------------------------- +// Notifications to section clients on cache events +//--------------------------------------------------------- +enum DataCacheNotificationType_t +{ + // Used internally to prohibit notifications + DC_NONE, + + // Item is falling off the LRU and should be deleted, return false to block + DC_AGE_DISCARD, + + // Item is being explicitly flushed and should be deleted, return false to block + DC_FLUSH_DISCARD, + + // Item is being explicitly removed and should be deleted. Failure is not an option + DC_REMOVED, + + // Cache is requesting item be relocated for debugging purposes + DC_RELOCATE, + + // Item info should be output to console, return false to accept default handling + DC_PRINT_INF0, +}; + +//------------------------------------- + +struct DataCacheNotification_t +{ + DataCacheNotificationType_t type; + const char * pszSectionName; + DataCacheClientID_t clientId; + const void * pItemData; + unsigned nItemSize; +}; + +//--------------------------------------------------------- + +const int DC_MAX_CLIENT_NAME = 15; +const int DC_MAX_ITEM_NAME = 511; + +//--------------------------------------------------------- +// Result codes +//--------------------------------------------------------- +enum DataCacheRemoveResult_t +{ + DC_OK, + DC_NOT_FOUND, + DC_LOCKED, +}; + +//--------------------------------------------------------- +// Add flags +//--------------------------------------------------------- +enum DataCacheAddFlags_t +{ + DCAF_LOCK = ( 1 << 0 ), + DCAF_DEFAULT = 0, +}; + + + +//----------------------------------------------------------------------------- +// IDataCacheSection +// +// Purpose: Implements a sub-section of the global cache. Subsections are +// areas of the cache with thier own memory constraints and common +// management. +//----------------------------------------------------------------------------- +abstract_class IDataCacheSection +{ +public: + //-------------------------------------------------------- + + virtual IDataCache *GetSharedCache() = 0; + virtual const char *GetName() = 0; + + //-------------------------------------------------------- + // Purpose: Controls cache size & options + //-------------------------------------------------------- + virtual void SetLimits( const DataCacheLimits_t &limits ) = 0; + virtual void SetOptions( unsigned options ) = 0; + + + //-------------------------------------------------------- + // Purpose: Get the current state of the section + //-------------------------------------------------------- + virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0; + + + //-------------------------------------------------------- + // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. + //-------------------------------------------------------- + virtual void EnsureCapacity( unsigned nBytes, unsigned nItems = 1 ) = 0; + + + //-------------------------------------------------------- + // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. + //-------------------------------------------------------- + virtual bool Add( DataCacheClientID_t clientId, const void *pItemData, unsigned size, DataCacheHandle_t *pHandle ) = 0; + + //-------------------------------------------------------- + // Purpose: Finds an item in the cache, returns NULL if item is not in cache. Not a cheap operation if section not configured for fast find. + //-------------------------------------------------------- + virtual DataCacheHandle_t Find( DataCacheClientID_t clientId ) = 0; + + + //-------------------------------------------------------- + // Purpose: Get an item out of the cache and remove it. No callbacks are executed unless explicity specified. + //-------------------------------------------------------- + virtual DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, const void **ppItemData, unsigned *pItemSize = NULL, bool bNotify = false ) = 0; + DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, bool bNotify = false ) { return Remove( handle, NULL, NULL, bNotify ); } + + + //-------------------------------------------------------- + // Purpose: Returns if the data is currently in memory, but does *not* change its location in the LRU + //-------------------------------------------------------- + virtual bool IsPresent( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Lock an item in the cache, returns NULL if item is not in the cache. + //-------------------------------------------------------- + virtual void *Lock( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Unlock a previous lock. + //-------------------------------------------------------- + virtual int Unlock( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Get an item without locking it, returns NULL if item is not in the cache. Use with care! + //-------------------------------------------------------- + virtual void *Get( DataCacheHandle_t handle, bool bFrameLock = false ) = 0; + virtual void *GetNoTouch( DataCacheHandle_t handle, bool bFrameLock = false ) = 0; + + //-------------------------------------------------------- + // Purpose: "Frame locking" (not game frame). A crude way to manage locks over relatively + // short periods. Does not affect normal locks/unlocks + //-------------------------------------------------------- + virtual int BeginFrameLocking() = 0; + virtual bool IsFrameLocking() = 0; + virtual void *FrameLock( DataCacheHandle_t handle ) = 0; + virtual int EndFrameLocking() = 0; + virtual int *GetFrameUnlockCounterPtr() = 0; + + + //-------------------------------------------------------- + // Purpose: Lock management, not for the feint of heart + //-------------------------------------------------------- + virtual int GetLockCount( DataCacheHandle_t handle ) = 0; + virtual int BreakLock( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Explicitly mark an item as "recently used" + //-------------------------------------------------------- + virtual bool Touch( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Explicitly mark an item as "least recently used". + //-------------------------------------------------------- + virtual bool Age( DataCacheHandle_t handle ) = 0; + + + //-------------------------------------------------------- + // Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified + //-------------------------------------------------------- + virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0; + + + //-------------------------------------------------------- + // Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed + //-------------------------------------------------------- + virtual unsigned Purge( unsigned nBytes ) = 0; + + + //-------------------------------------------------------- + // Purpose: Output the state of the section + //-------------------------------------------------------- + virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT ) = 0; + + //-------------------------------------------------------- + // Purpose: Updates the size used by a specific item (locks the item, kicks + // other items out to make room as necessary, unlocks the item). + //-------------------------------------------------------- + virtual void UpdateSize( DataCacheHandle_t handle, unsigned int nNewSize ) = 0; + + + //-------------------------------------------------------- + // Purpose: Access to the mutex. More explicit control during get-then-lock sequences + // to ensure object stays valid during "then" + //-------------------------------------------------------- + virtual void LockMutex() = 0; + virtual void UnlockMutex() = 0; + + //-------------------------------------------------------- + // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. + //-------------------------------------------------------- + virtual bool AddEx( DataCacheClientID_t clientId, const void *pItemData, unsigned size, unsigned flags, DataCacheHandle_t *pHandle ) = 0; +}; + + +//----------------------------------------------------------------------------- +// IDataCacheClient +// +// Purpose: Connection between the cache and the owner of a cache section +// +//----------------------------------------------------------------------------- +abstract_class IDataCacheClient +{ +public: + //-------------------------------------------------------- + // + //-------------------------------------------------------- + virtual bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) = 0; + + + //-------------------------------------------------------- + // + //-------------------------------------------------------- + virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen ) = 0; +}; + +//------------------------------------- + +class CDefaultDataCacheClient : public IDataCacheClient +{ +public: + virtual bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) + { + switch ( notification.type ) + { + case DC_AGE_DISCARD: + case DC_FLUSH_DISCARD: + case DC_REMOVED: + default: + Assert ( 0 ); + return false; + } + return false; + } + + virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen ) + { + return false; + } +}; + + +//----------------------------------------------------------------------------- +// IDataCache +// +// Purpose: The global shared cache. Manages sections and overall budgets. +// +//----------------------------------------------------------------------------- +abstract_class IDataCache : public IAppSystem +{ +public: + //-------------------------------------------------------- + // Purpose: Controls cache size. + //-------------------------------------------------------- + virtual void SetSize( int nMaxBytes ) = 0; + virtual void SetOptions( unsigned options ) = 0; + virtual void SetSectionLimits( const char *pszSectionName, const DataCacheLimits_t &limits ) = 0; + + + //-------------------------------------------------------- + // Purpose: Get the current state of the cache + //-------------------------------------------------------- + virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0; + + + //-------------------------------------------------------- + // Purpose: Add a section to the cache + //-------------------------------------------------------- + virtual IDataCacheSection *AddSection( IDataCacheClient *pClient, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false ) = 0; + + + //-------------------------------------------------------- + // Purpose: Remove a section from the cache + //-------------------------------------------------------- + virtual void RemoveSection( const char *pszClientName, bool bCallFlush = true ) = 0; + void RemoveSection( IDataCacheSection *pSection, bool bCallFlush = true ) { if ( pSection) RemoveSection( pSection->GetName() ); } + + + //-------------------------------------------------------- + // Purpose: Find a section of the cache + //-------------------------------------------------------- + virtual IDataCacheSection *FindSection( const char *pszClientName ) = 0; + + + //-------------------------------------------------------- + // Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed + //-------------------------------------------------------- + virtual unsigned Purge( unsigned nBytes ) = 0; + + + //-------------------------------------------------------- + // Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified + //-------------------------------------------------------- + virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0; + + + //-------------------------------------------------------- + // Purpose: Output the state of the cache + //-------------------------------------------------------- + virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT, const char *pszSection = NULL ) = 0; +}; + +//----------------------------------------------------------------------------- +// Helper class to support usage pattern similar to CDataManager +//----------------------------------------------------------------------------- + +template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE * > +class CManagedDataCacheClient : public CDefaultDataCacheClient +{ +public: + typedef CManagedDataCacheClient<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE> CCacheClientBaseClass; + + CManagedDataCacheClient() + : m_pCache( NULL ) + { + } + + void Init( IDataCache *pSharedCache, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false ) + { + if ( !m_pCache ) + { + m_pCache = pSharedCache->AddSection( this, pszSectionName, limits, bSupportFastFind ); + } + } + + void Shutdown() + { + if ( m_pCache ) + { + m_pCache->GetSharedCache()->RemoveSection( m_pCache ); + m_pCache = NULL; + } + } + + LOCK_TYPE CacheGet( DataCacheHandle_t handle, bool bFrameLock = true ) + { + return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Get( handle, bFrameLock ))->GetData()); + } + + LOCK_TYPE CacheGetNoTouch( DataCacheHandle_t handle ) + { + return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->GetNoTouch( handle ))->GetData()); + } + + LOCK_TYPE CacheLock( DataCacheHandle_t handle ) + { + return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Lock( handle ))->GetData()); + } + + int CacheUnlock( DataCacheHandle_t handle ) + { + return m_pCache->Unlock( handle ); + } + + void CacheTouch( DataCacheHandle_t handle ) + { + m_pCache->Touch( handle ); + } + + void CacheRemove( DataCacheHandle_t handle, bool bNotify = true ) + { + m_pCache->Remove( handle, bNotify ); + } + + void CacheFlush() + { + m_pCache->Flush(); + } + + DataCacheHandle_t CacheCreate( const CREATE_PARAMS &createParams, unsigned flags = DCAF_DEFAULT ) + { + m_pCache->EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams)); + STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams ); + DataCacheHandle_t handle; + m_pCache->AddEx( (DataCacheClientID_t)pStore, pStore, pStore->Size(), flags, &handle); + return handle; + } + + void CacheLockMutex() + { + m_pCache->LockMutex(); + } + + void CacheUnlockMutex() + { + m_pCache->UnlockMutex(); + } + + bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) + { + switch ( notification.type ) + { + case DC_AGE_DISCARD: + case DC_FLUSH_DISCARD: + case DC_REMOVED: + { + STORAGE_TYPE *p = (STORAGE_TYPE *)notification.clientId; + p->DestroyResource(); + } + return true; + default: + return CDefaultDataCacheClient::HandleCacheNotification( notification ); + } + } + + +protected: + + ~CManagedDataCacheClient() + { + Shutdown(); + } + + IDataCacheSection *GetCacheSection() + { + return m_pCache; + } + +private: + IDataCacheSection *m_pCache; + +}; + +//----------------------------------------------------------------------------- + +#endif // IDataCache |