Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

296 lines
8.0 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef RESOURCEMANAGER_H
  7. #define RESOURCEMANAGER_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier0/threadtools.h"
  12. #include "utlmultilist.h"
  13. #include "utlvector.h"
  14. FORWARD_DECLARE_HANDLE( memhandle_t );
  15. #define INVALID_MEMHANDLE ((memhandle_t)0xffffffff)
  16. class CDataManagerBase
  17. {
  18. public:
  19. // public API
  20. // -----------------------------------------------------------------------------
  21. // memhandle_t CreateResource( params ) // implemented by derived class
  22. void DestroyResource( memhandle_t handle );
  23. // type-safe implementation in derived class
  24. //void *LockResource( memhandle_t handle );
  25. int UnlockResource( memhandle_t handle );
  26. void TouchResource( memhandle_t handle );
  27. void MarkAsStale( memhandle_t handle ); // move to head of LRU
  28. int LockCount( memhandle_t handle );
  29. int BreakLock( memhandle_t handle );
  30. int BreakAllLocks();
  31. // HACKHACK: For convenience - offers no lock protection
  32. // type-safe implementation in derived class
  33. //void *GetResource_NoLock( memhandle_t handle );
  34. unsigned int TargetSize();
  35. unsigned int AvailableSize();
  36. unsigned int UsedSize();
  37. void NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize );
  38. void SetTargetSize( unsigned int targetSize );
  39. // NOTE: flush is equivalent to Destroy
  40. unsigned int FlushAllUnlocked();
  41. unsigned int FlushToTargetSize();
  42. unsigned int FlushAll();
  43. unsigned int Purge( unsigned int nBytesToPurge );
  44. unsigned int EnsureCapacity( unsigned int size );
  45. // Thread lock
  46. virtual void Lock() {}
  47. virtual bool TryLock() { return true; }
  48. virtual void Unlock() {}
  49. // Iteration
  50. // -----------------------------------------------------------------------------
  51. void SetFreeOnDestruct( bool value ) { m_freeOnDestruct = value; }
  52. // Debugging only!!!!
  53. void GetLRUHandleList( CUtlVector< memhandle_t >& list );
  54. void GetLockHandleList( CUtlVector< memhandle_t >& list );
  55. protected:
  56. // derived class must call these to implement public API
  57. unsigned short CreateHandle( bool bCreateLocked );
  58. memhandle_t StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize );
  59. void *GetResource_NoLock( memhandle_t handle );
  60. void *GetResource_NoLockNoLRUTouch( memhandle_t handle );
  61. void *LockResource( memhandle_t handle );
  62. void *LockResourceReturnCount( int *pCount, memhandle_t handle );
  63. // NOTE: you must call this from the destructor of the derived class! (will assert otherwise)
  64. void FreeAllLists() { FlushAll(); m_listsAreFreed = true; }
  65. CDataManagerBase( unsigned int maxSize );
  66. virtual ~CDataManagerBase();
  67. inline unsigned int MemTotal_Inline() const { return m_targetMemorySize; }
  68. inline unsigned int MemAvailable_Inline() const { return m_targetMemorySize - m_memUsed; }
  69. inline unsigned int MemUsed_Inline() const { return m_memUsed; }
  70. // Implemented by derived class:
  71. virtual void DestroyResourceStorage( void * ) = 0;
  72. virtual unsigned int GetRealSize( void * ) = 0;
  73. memhandle_t ToHandle( unsigned short index );
  74. unsigned short FromHandle( memhandle_t handle );
  75. void TouchByIndex( unsigned short memoryIndex );
  76. void * GetForFreeByIndex( unsigned short memoryIndex );
  77. // One of these is stored per active allocation
  78. struct resource_lru_element_t
  79. {
  80. resource_lru_element_t()
  81. {
  82. lockCount = 0;
  83. serial = 1;
  84. pStore = 0;
  85. }
  86. unsigned short lockCount;
  87. unsigned short serial;
  88. void *pStore;
  89. };
  90. unsigned int m_targetMemorySize;
  91. unsigned int m_memUsed;
  92. CUtlMultiList< resource_lru_element_t, unsigned short > m_memoryLists;
  93. unsigned short m_lruList;
  94. unsigned short m_lockList;
  95. unsigned short m_freeList;
  96. unsigned short m_listsAreFreed : 1;
  97. unsigned short m_freeOnDestruct : 1;
  98. unsigned short m_unused : 14;
  99. };
  100. template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE *, class MUTEX_TYPE = CThreadNullMutex>
  101. class CDataManager : public CDataManagerBase
  102. {
  103. typedef CDataManagerBase BaseClass;
  104. public:
  105. CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>( unsigned int size = (unsigned)-1 ) : BaseClass(size) {}
  106. ~CDataManager<STORAGE_TYPE, CREATE_PARAMS, LOCK_TYPE, MUTEX_TYPE>()
  107. {
  108. // NOTE: This must be called in all implementations of CDataManager
  109. if ( m_freeOnDestruct )
  110. {
  111. FreeAllLists();
  112. }
  113. }
  114. // Use GetData() to translate pointer to LOCK_TYPE
  115. LOCK_TYPE LockResource( memhandle_t hMem )
  116. {
  117. void *pLock = BaseClass::LockResource( hMem );
  118. if ( pLock )
  119. {
  120. return StoragePointer(pLock)->GetData();
  121. }
  122. return NULL;
  123. }
  124. LOCK_TYPE LockResourceReturnCount( int *pCount, memhandle_t hMem )
  125. {
  126. void *pLock = BaseClass::LockResourceReturnCount( pCount, hMem );
  127. if ( pLock )
  128. {
  129. return StoragePointer(pLock)->GetData();
  130. }
  131. return NULL;
  132. }
  133. // Use GetData() to translate pointer to LOCK_TYPE
  134. LOCK_TYPE GetResource_NoLock( memhandle_t hMem )
  135. {
  136. void *pLock = const_cast<void *>(BaseClass::GetResource_NoLock( hMem ));
  137. if ( pLock )
  138. {
  139. return StoragePointer(pLock)->GetData();
  140. }
  141. return NULL;
  142. }
  143. // Use GetData() to translate pointer to LOCK_TYPE
  144. // Doesn't touch the memory LRU
  145. LOCK_TYPE GetResource_NoLockNoLRUTouch( memhandle_t hMem )
  146. {
  147. void *pLock = const_cast<void *>(BaseClass::GetResource_NoLockNoLRUTouch( hMem ));
  148. if ( pLock )
  149. {
  150. return StoragePointer(pLock)->GetData();
  151. }
  152. return NULL;
  153. }
  154. // Wrapper to match implementation of allocation with typed storage & alloc params.
  155. memhandle_t CreateResource( const CREATE_PARAMS &createParams, bool bCreateLocked = false )
  156. {
  157. BaseClass::EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams));
  158. STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams );
  159. AUTO_LOCK_( CDataManagerBase, *this );
  160. unsigned short memoryIndex = BaseClass::CreateHandle( bCreateLocked );
  161. return BaseClass::StoreResourceInHandle( memoryIndex, pStore, pStore->Size() );
  162. }
  163. // Iteration. Must lock first
  164. memhandle_t GetFirstUnlocked()
  165. {
  166. unsigned node = m_memoryLists.Head(m_lruList);
  167. if ( node == m_memoryLists.InvalidIndex() )
  168. {
  169. return INVALID_MEMHANDLE;
  170. }
  171. return ToHandle( node );
  172. }
  173. memhandle_t GetFirstLocked()
  174. {
  175. unsigned node = m_memoryLists.Head(m_lockList);
  176. if ( node == m_memoryLists.InvalidIndex() )
  177. {
  178. return INVALID_MEMHANDLE;
  179. }
  180. return ToHandle( node );
  181. }
  182. memhandle_t GetNext( memhandle_t hPrev )
  183. {
  184. if ( hPrev == INVALID_MEMHANDLE )
  185. {
  186. return INVALID_MEMHANDLE;
  187. }
  188. unsigned short iNext = m_memoryLists.Next( FromHandle( hPrev ) );
  189. if ( iNext == m_memoryLists.InvalidIndex() )
  190. {
  191. return INVALID_MEMHANDLE;
  192. }
  193. return ToHandle( iNext );
  194. }
  195. MUTEX_TYPE &AccessMutex() { return m_mutex; }
  196. virtual void Lock() { m_mutex.Lock(); }
  197. virtual bool TryLock() { return m_mutex.TryLock(); }
  198. virtual void Unlock() { m_mutex.Unlock(); }
  199. private:
  200. STORAGE_TYPE *StoragePointer( void *pMem )
  201. {
  202. return static_cast<STORAGE_TYPE *>(pMem);
  203. }
  204. virtual void DestroyResourceStorage( void *pStore )
  205. {
  206. StoragePointer(pStore)->DestroyResource();
  207. }
  208. virtual unsigned int GetRealSize( void *pStore )
  209. {
  210. return StoragePointer(pStore)->Size();
  211. }
  212. MUTEX_TYPE m_mutex;
  213. };
  214. //-----------------------------------------------------------------------------
  215. inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle )
  216. {
  217. unsigned int fullWord = (unsigned int)reinterpret_cast<uintp>( handle );
  218. unsigned short serial = fullWord>>16;
  219. unsigned short index = fullWord & 0xFFFF;
  220. index--;
  221. if ( m_memoryLists.IsValidIndex(index) && m_memoryLists[index].serial == serial )
  222. return index;
  223. return m_memoryLists.InvalidIndex();
  224. }
  225. inline int CDataManagerBase::LockCount( memhandle_t handle )
  226. {
  227. Lock();
  228. int result = 0;
  229. unsigned short memoryIndex = FromHandle(handle);
  230. if ( memoryIndex != m_memoryLists.InvalidIndex() )
  231. {
  232. result = m_memoryLists[memoryIndex].lockCount;
  233. }
  234. Unlock();
  235. return result;
  236. }
  237. #endif // RESOURCEMANAGER_H