#ifndef IDATACACHE_H #define IDATACACHE_H #ifdef _WIN32 #pragma once #endif #include "dbg.h" #include "IAppSystem.h" class IDataCache; #define DATACACHE_INTERFACE_VERSION "VDataCache003" typedef uint32 DataCacheClientID_t; FORWARD_DECLARE_HANDLE(memhandle_t); typedef memhandle_t DataCacheHandle_t; #define DC_INVALID_HANDLE ((DataCacheHandle_t)0) 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) { } unsigned nMaxBytes; unsigned nMaxItems; unsigned nMinBytes; unsigned nMinItems; }; struct DataCacheStatus_t { unsigned nBytes; unsigned nItems; unsigned nBytesLocked; unsigned nItemsLocked; unsigned nFindRequests; unsigned nFindHits; }; enum DataCacheOptions_t { DC_TRACE_ACTIVITY = (1 << 0), DC_FORCE_RELOCATE = (1 << 1), DC_ALWAYS_MISS = (1 << 2), DC_VALIDATE = (1 << 3), }; enum DataCacheReportType_t { DC_SUMMARY_REPORT, DC_DETAIL_REPORT, DC_DETAIL_REPORT_LRU, }; enum DataCacheNotificationType_t { DC_NONE, DC_AGE_DISCARD, DC_FLUSH_DISCARD, DC_REMOVED, DC_RELOCATE, 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; enum DataCacheRemoveResult_t { DC_OK, DC_NOT_FOUND, DC_LOCKED, }; enum DataCacheAddFlags_t { DCAF_LOCK = (1 << 0), DCAF_DEFAULT = 0, }; abstract_class IDataCacheSection { public: virtual IDataCache * GetSharedCache() = 0; virtual const char* GetName() = 0; virtual void SetLimits(const DataCacheLimits_t& limits) = 0; virtual void SetOptions(unsigned options) = 0; virtual void GetStatus(DataCacheStatus_t* pStatus, DataCacheLimits_t* pLimits = NULL) = 0; virtual void EnsureCapacity(unsigned nBytes, unsigned nItems = 1) = 0; virtual bool Add(DataCacheClientID_t clientId, const void* pItemData, unsigned size, DataCacheHandle_t* pHandle) = 0; virtual DataCacheHandle_t Find(DataCacheClientID_t clientId) = 0; 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); } virtual bool IsPresent(DataCacheHandle_t handle) = 0; virtual void* Lock(DataCacheHandle_t handle) = 0; virtual int Unlock(DataCacheHandle_t handle) = 0; virtual void* Get(DataCacheHandle_t handle, bool bFrameLock = false) = 0; virtual void* GetNoTouch(DataCacheHandle_t handle, bool bFrameLock = false) = 0; virtual int BeginFrameLocking() = 0; virtual bool IsFrameLocking() = 0; virtual void* FrameLock(DataCacheHandle_t handle) = 0; virtual int EndFrameLocking() = 0; virtual int* GetFrameUnlockCounterPtr() = 0; virtual int GetLockCount(DataCacheHandle_t handle) = 0; virtual int BreakLock(DataCacheHandle_t handle) = 0; virtual bool Touch(DataCacheHandle_t handle) = 0; virtual bool Age(DataCacheHandle_t handle) = 0; virtual unsigned Flush(bool bUnlockedOnly = true, bool bNotify = true) = 0; virtual unsigned Purge(unsigned nBytes) = 0; virtual void OutputReport(DataCacheReportType_t reportType = DC_SUMMARY_REPORT) = 0; virtual void UpdateSize(DataCacheHandle_t handle, unsigned int nNewSize) = 0; virtual void LockMutex() = 0; virtual void UnlockMutex() = 0; virtual bool AddEx(DataCacheClientID_t clientId, const void* pItemData, unsigned size, unsigned flags, DataCacheHandle_t* pHandle) = 0; }; abstract_class IDataCacheClient { public: virtual bool HandleCacheNotification(const DataCacheNotification_t & notification) = 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& notification) { 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; } }; abstract_class IDataCache : public IAppSystem { public: virtual void SetSize(int nMaxBytes) = 0; virtual void SetOptions(unsigned options) = 0; virtual void SetSectionLimits(const char* pszSectionName, const DataCacheLimits_t& limits) = 0; virtual void GetStatus(DataCacheStatus_t* pStatus, DataCacheLimits_t* pLimits = NULL) = 0; virtual IDataCacheSection* AddSection(IDataCacheClient* pClient, const char* pszSectionName, const DataCacheLimits_t& limits = DataCacheLimits_t(), bool bSupportFastFind = false) = 0; virtual void RemoveSection(const char* pszClientName, bool bCallFlush = true) = 0; void RemoveSection(IDataCacheSection* pSection, bool bCallFlush = true) { if (pSection) RemoveSection(pSection->GetName()); } virtual IDataCacheSection* FindSection(const char* pszClientName) = 0; virtual unsigned Purge(unsigned nBytes) = 0; virtual unsigned Flush(bool bUnlockedOnly = true, bool bNotify = true) = 0; virtual void OutputReport(DataCacheReportType_t reportType = DC_SUMMARY_REPORT, const char* pszSection = NULL) = 0; }; template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE* > class CManagedDataCacheClient : public CDefaultDataCacheClient { public: typedef CManagedDataCacheClient 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& notification) { 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