diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/public/tier1/datamanager.h | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/public/tier1/datamanager.h')
| -rw-r--r-- | mp/src/public/tier1/datamanager.h | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/mp/src/public/tier1/datamanager.h b/mp/src/public/tier1/datamanager.h new file mode 100644 index 00000000..6c72bf9e --- /dev/null +++ b/mp/src/public/tier1/datamanager.h @@ -0,0 +1,277 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef RESOURCEMANAGER_H
+#define RESOURCEMANAGER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/threadtools.h"
+#include "utlmultilist.h"
+#include "utlvector.h"
+
+FORWARD_DECLARE_HANDLE( memhandle_t );
+
+#define INVALID_MEMHANDLE ((memhandle_t)0xffffffff)
+
+class CDataManagerBase
+{
+public:
+
+ // public API
+ // -----------------------------------------------------------------------------
+ // memhandle_t CreateResource( params ) // implemented by derived class
+ void DestroyResource( memhandle_t handle );
+
+ // type-safe implementation in derived class
+ //void *LockResource( memhandle_t handle );
+ int UnlockResource( memhandle_t handle );
+ void TouchResource( memhandle_t handle );
+ void MarkAsStale( memhandle_t handle ); // move to head of LRU
+
+ int LockCount( memhandle_t handle );
+ int BreakLock( memhandle_t handle );
+ int BreakAllLocks();
+
+ // HACKHACK: For convenience - offers no lock protection
+ // type-safe implementation in derived class
+ //void *GetResource_NoLock( memhandle_t handle );
+
+ unsigned int TargetSize();
+ unsigned int AvailableSize();
+ unsigned int UsedSize();
+
+ void NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize );
+
+ void SetTargetSize( unsigned int targetSize );
+
+ // NOTE: flush is equivalent to Destroy
+ unsigned int FlushAllUnlocked();
+ unsigned int FlushToTargetSize();
+ unsigned int FlushAll();
+ unsigned int Purge( unsigned int nBytesToPurge );
+ unsigned int EnsureCapacity( unsigned int size );
+
+ // Thread lock
+ virtual void Lock() {}
+ virtual bool TryLock() { return true; }
+ virtual void Unlock() {}
+
+ // Iteration
+
+ // -----------------------------------------------------------------------------
+
+ // Debugging only!!!!
+ void GetLRUHandleList( CUtlVector< memhandle_t >& list );
+ void GetLockHandleList( CUtlVector< memhandle_t >& list );
+
+
+protected:
+ // derived class must call these to implement public API
+ unsigned short CreateHandle( bool bCreateLocked );
+ memhandle_t StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize );
+ void *GetResource_NoLock( memhandle_t handle );
+ void *GetResource_NoLockNoLRUTouch( memhandle_t handle );
+ void *LockResource( memhandle_t handle );
+
+ // NOTE: you must call this from the destructor of the derived class! (will assert otherwise)
+ void FreeAllLists() { FlushAll(); m_listsAreFreed = true; }
+
+ CDataManagerBase( unsigned int maxSize );
+ virtual ~CDataManagerBase();
+
+
+ inline unsigned int MemTotal_Inline() const { return m_targetMemorySize; }
+ inline unsigned int MemAvailable_Inline() const { return m_targetMemorySize - m_memUsed; }
+ inline unsigned int MemUsed_Inline() const { return m_memUsed; }
+
+// Implemented by derived class:
+ virtual void DestroyResourceStorage( void * ) = 0;
+ virtual unsigned int GetRealSize( void * ) = 0;
+
+ memhandle_t ToHandle( unsigned short index );
+ unsigned short FromHandle( memhandle_t handle );
+
+ void TouchByIndex( unsigned short memoryIndex );
+ void * GetForFreeByIndex( unsigned short memoryIndex );
+
+ // One of these is stored per active allocation
+ struct resource_lru_element_t
+ {
+ resource_lru_element_t()
+ {
+ lockCount = 0;
+ serial = 1;
+ pStore = 0;
+ }
+
+ unsigned short lockCount;
+ unsigned short serial;
+ void *pStore;
+ };
+
+ unsigned int m_targetMemorySize;
+ unsigned int m_memUsed;
+
+ CUtlMultiList< resource_lru_element_t, unsigned short > m_memoryLists;
+
+ unsigned short m_lruList;
+ unsigned short m_lockList;
+ unsigned short m_freeList;
+ unsigned short m_listsAreFreed : 1;
+ unsigned short m_unused : 15;
+
+};
+
+template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE *, class MUTEX_TYPE = CThreadNullMutex>
+class CDataManager : public CDataManagerBase
+{
+ typedef CDataManagerBase BaseClass;
+public:
+
+ CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>( unsigned int size = (unsigned)-1 ) : BaseClass(size) {}
+
+
+ ~CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>()
+ {
+ // NOTE: This must be called in all implementations of CDataManager
+ FreeAllLists();
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ LOCK_TYPE LockResource( memhandle_t hMem )
+ {
+ void *pLock = BaseClass::LockResource( hMem );
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+
+ return NULL;
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ LOCK_TYPE GetResource_NoLock( memhandle_t hMem )
+ {
+ void *pLock = const_cast<void *>(BaseClass::GetResource_NoLock( hMem ));
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+ return NULL;
+ }
+
+ // Use GetData() to translate pointer to LOCK_TYPE
+ // Doesn't touch the memory LRU
+ LOCK_TYPE GetResource_NoLockNoLRUTouch( memhandle_t hMem )
+ {
+ void *pLock = const_cast<void *>(BaseClass::GetResource_NoLockNoLRUTouch( hMem ));
+ if ( pLock )
+ {
+ return StoragePointer(pLock)->GetData();
+ }
+ return NULL;
+ }
+
+ // Wrapper to match implementation of allocation with typed storage & alloc params.
+ memhandle_t CreateResource( const CREATE_PARAMS &createParams, bool bCreateLocked = false )
+ {
+ BaseClass::EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams));
+ unsigned short memoryIndex = BaseClass::CreateHandle( bCreateLocked );
+ STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams );
+ return BaseClass::StoreResourceInHandle( memoryIndex, pStore, pStore->Size() );
+ }
+
+ // Iteration. Must lock first
+ memhandle_t GetFirstUnlocked()
+ {
+ unsigned node = m_memoryLists.Head(m_lruList);
+ if ( node == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+ return ToHandle( node );
+ }
+
+ memhandle_t GetFirstLocked()
+ {
+ unsigned node = m_memoryLists.Head(m_lockList);
+ if ( node == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+ return ToHandle( node );
+ }
+
+ memhandle_t GetNext( memhandle_t hPrev )
+ {
+ if ( hPrev == INVALID_MEMHANDLE )
+ {
+ return INVALID_MEMHANDLE;
+ }
+
+ unsigned short iNext = m_memoryLists.Next( FromHandle( hPrev ) );
+ if ( iNext == m_memoryLists.InvalidIndex() )
+ {
+ return INVALID_MEMHANDLE;
+ }
+
+ return ToHandle( iNext );
+ }
+
+ MUTEX_TYPE &AccessMutex() { return m_mutex; }
+ virtual void Lock() { m_mutex.Lock(); }
+ virtual bool TryLock() { return m_mutex.TryLock(); }
+ virtual void Unlock() { m_mutex.Unlock(); }
+
+private:
+ STORAGE_TYPE *StoragePointer( void *pMem )
+ {
+ return static_cast<STORAGE_TYPE *>(pMem);
+ }
+
+ virtual void DestroyResourceStorage( void *pStore )
+ {
+ StoragePointer(pStore)->DestroyResource();
+ }
+
+ virtual unsigned int GetRealSize( void *pStore )
+ {
+ return StoragePointer(pStore)->Size();
+ }
+
+ MUTEX_TYPE m_mutex;
+};
+
+//-----------------------------------------------------------------------------
+
+inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle )
+{
+ unsigned int fullWord = (unsigned int)handle;
+ unsigned short serial = fullWord>>16;
+ unsigned short index = fullWord & 0xFFFF;
+ index--;
+ if ( m_memoryLists.IsValidIndex(index) && m_memoryLists[index].serial == serial )
+ return index;
+ return m_memoryLists.InvalidIndex();
+}
+
+inline int CDataManagerBase::LockCount( memhandle_t handle )
+{
+ Lock();
+ int result = 0;
+ unsigned short memoryIndex = FromHandle(handle);
+ if ( memoryIndex != m_memoryLists.InvalidIndex() )
+ {
+ result = m_memoryLists[memoryIndex].lockCount;
+ }
+ Unlock();
+ return result;
+}
+
+
+#endif // RESOURCEMANAGER_H
|