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.

586 lines
16 KiB

  1. //====== Copyright � 1996-2004, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef UTLHANDLETABLE_H
  7. #define UTLHANDLETABLE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier1/utlvector.h"
  12. #include "tier1/utlqueue.h"
  13. //-----------------------------------------------------------------------------
  14. // Handles are 32 bits. Invalid handles are all 1s
  15. //-----------------------------------------------------------------------------
  16. typedef unsigned int UtlHandle_t;
  17. #define UTLHANDLE_INVALID ((UtlHandle_t)~0)
  18. //-----------------------------------------------------------------------------
  19. // Purpose: This is a table used to allocate handles
  20. // HandleBits specifies the max # of simultaneously allocated handles.
  21. // An extra bit is used for the validity state
  22. // The rest of the 32 bits are used for a serial number
  23. //-----------------------------------------------------------------------------
  24. template< class T, int HandleBits >
  25. class CUtlHandleTable
  26. {
  27. public:
  28. CUtlHandleTable();
  29. // Allocate, deallocate handles
  30. UtlHandle_t AddHandle();
  31. void RemoveHandle( UtlHandle_t h );
  32. // Set/get handle values
  33. void SetHandle( UtlHandle_t h, T *pData );
  34. T *GetHandle( UtlHandle_t h ) const;
  35. T *GetHandle( UtlHandle_t h, bool checkValidity ) const;
  36. // Is a handle valid?
  37. bool IsHandleValid( UtlHandle_t h ) const;
  38. // Iterate over handles; they may not be valid
  39. unsigned int GetValidHandleCount() const;
  40. unsigned int GetHandleCount() const;
  41. UtlHandle_t GetHandleFromIndex( int i ) const;
  42. int GetIndexFromHandle( UtlHandle_t h ) const;
  43. void MarkHandleInvalid( UtlHandle_t h );
  44. void MarkHandleValid( UtlHandle_t h );
  45. private:
  46. struct HandleType_t
  47. {
  48. HandleType_t( unsigned int i, unsigned int s ) : nIndex( i ), nSerial( s )
  49. {
  50. Assert( i < ( 1 << HandleBits ) );
  51. Assert( s < ( 1 << ( 31 - HandleBits ) ) );
  52. }
  53. unsigned int nIndex : HandleBits;
  54. unsigned int nSerial : 32 - HandleBits;
  55. };
  56. struct EntryType_t
  57. {
  58. EntryType_t() : m_nSerial( 0 ), nInvalid( 0 ), m_pData( 0 ) {}
  59. unsigned int m_nSerial : 31;
  60. unsigned int nInvalid : 1;
  61. T *m_pData;
  62. };
  63. static unsigned int GetSerialNumber( UtlHandle_t handle );
  64. static unsigned int GetListIndex( UtlHandle_t handle );
  65. static UtlHandle_t CreateHandle( unsigned int nSerial, unsigned int nIndex );
  66. const EntryType_t *GetEntry( UtlHandle_t handle, bool checkValidity ) const;
  67. unsigned int m_nValidHandles;
  68. CUtlVector< EntryType_t > m_list;
  69. CUtlQueue< int > m_unused;
  70. };
  71. //-----------------------------------------------------------------------------
  72. // Constructor, destructor
  73. //-----------------------------------------------------------------------------
  74. template< class T, int HandleBits >
  75. CUtlHandleTable<T, HandleBits>::CUtlHandleTable() : m_nValidHandles( 0 )
  76. {
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Allocate, deallocate handles
  80. //-----------------------------------------------------------------------------
  81. template< class T, int HandleBits >
  82. UtlHandle_t CUtlHandleTable<T, HandleBits>::AddHandle()
  83. {
  84. unsigned int nIndex = ( m_unused.Count() > 0 ) ? m_unused.RemoveAtHead() : m_list.AddToTail();
  85. EntryType_t &entry = m_list[ nIndex ];
  86. entry.nInvalid = 0;
  87. entry.m_pData = NULL;
  88. ++m_nValidHandles;
  89. return CreateHandle( entry.m_nSerial, nIndex );
  90. }
  91. template< class T, int HandleBits >
  92. void CUtlHandleTable<T, HandleBits>::RemoveHandle( UtlHandle_t handle )
  93. {
  94. unsigned int nIndex = GetListIndex( handle );
  95. Assert( nIndex < ( unsigned int )m_list.Count() );
  96. if ( nIndex >= ( unsigned int )m_list.Count() )
  97. return;
  98. EntryType_t &entry = m_list[ nIndex ];
  99. ++entry.m_nSerial; // mark old serial# invalid
  100. if ( !entry.nInvalid )
  101. {
  102. entry.nInvalid = 1;
  103. --m_nValidHandles;
  104. }
  105. entry.m_pData = NULL;
  106. // If a handle has been used this many times, then we need to take it out of service, otherwise if the
  107. // serial # wraps around we'll possibly revalidate old handles and they'll start to point at the wrong objects. Unlikely, but possible.
  108. bool bStopUsing = ( entry.m_nSerial >= ( (1 << ( 31 - HandleBits ) ) - 1 ) );
  109. if ( !bStopUsing )
  110. {
  111. m_unused.Insert( nIndex );
  112. }
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Set/get handle values
  116. //-----------------------------------------------------------------------------
  117. template< class T, int HandleBits >
  118. void CUtlHandleTable<T, HandleBits>::SetHandle( UtlHandle_t handle, T *pData )
  119. {
  120. EntryType_t *entry = const_cast< EntryType_t* >( GetEntry( handle, false ) );
  121. Assert( entry );
  122. if ( entry == NULL )
  123. return;
  124. // Validate the handle
  125. if ( entry->nInvalid )
  126. {
  127. ++m_nValidHandles;
  128. entry->nInvalid = 0;
  129. }
  130. entry->m_pData = pData;
  131. }
  132. template< class T, int HandleBits >
  133. T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle ) const
  134. {
  135. const EntryType_t *entry = GetEntry( handle, true );
  136. return entry ? entry->m_pData : NULL;
  137. }
  138. template< class T, int HandleBits >
  139. T *CUtlHandleTable<T, HandleBits>::GetHandle( UtlHandle_t handle, bool checkValidity ) const
  140. {
  141. const EntryType_t *entry = GetEntry( handle, checkValidity );
  142. return entry ? entry->m_pData : NULL;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Is a handle valid?
  146. //-----------------------------------------------------------------------------
  147. template< class T, int HandleBits >
  148. bool CUtlHandleTable<T, HandleBits>::IsHandleValid( UtlHandle_t handle ) const
  149. {
  150. if ( handle == UTLHANDLE_INVALID )
  151. return false;
  152. unsigned int nIndex = GetListIndex( handle );
  153. AssertOnce( nIndex < ( unsigned int )m_list.Count() );
  154. if ( nIndex >= ( unsigned int )m_list.Count() )
  155. return false;
  156. const EntryType_t &entry = m_list[ nIndex ];
  157. if ( entry.m_nSerial != GetSerialNumber( handle ) )
  158. return false;
  159. if ( 1 == entry.nInvalid )
  160. return false;
  161. return true;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Current max handle
  165. //-----------------------------------------------------------------------------
  166. template< class T, int HandleBits >
  167. unsigned int CUtlHandleTable<T, HandleBits>::GetValidHandleCount() const
  168. {
  169. return m_nValidHandles;
  170. }
  171. template< class T, int HandleBits >
  172. unsigned int CUtlHandleTable<T, HandleBits>::GetHandleCount() const
  173. {
  174. return m_list.Count();
  175. }
  176. template< class T, int HandleBits >
  177. UtlHandle_t CUtlHandleTable<T, HandleBits>::GetHandleFromIndex( int i ) const
  178. {
  179. if ( m_list[i].m_pData )
  180. return CreateHandle( m_list[i].m_nSerial, i );
  181. return UTLHANDLE_INVALID;
  182. }
  183. template< class T, int HandleBits >
  184. int CUtlHandleTable<T, HandleBits>::GetIndexFromHandle( UtlHandle_t h ) const
  185. {
  186. if ( h == UTLHANDLE_INVALID )
  187. return -1;
  188. return GetListIndex( h );
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Cracking handles into indices + serial numbers
  192. //-----------------------------------------------------------------------------
  193. template< class T, int HandleBits >
  194. unsigned int CUtlHandleTable<T, HandleBits>::GetSerialNumber( UtlHandle_t handle )
  195. {
  196. return ( ( HandleType_t* )&handle )->nSerial;
  197. }
  198. template< class T, int HandleBits >
  199. unsigned int CUtlHandleTable<T, HandleBits>::GetListIndex( UtlHandle_t handle )
  200. {
  201. return ( ( HandleType_t* )&handle )->nIndex;
  202. }
  203. template< class T, int HandleBits >
  204. UtlHandle_t CUtlHandleTable<T, HandleBits>::CreateHandle( unsigned int nSerial, unsigned int nIndex )
  205. {
  206. HandleType_t h( nIndex, nSerial );
  207. return *( UtlHandle_t* )&h;
  208. }
  209. //-----------------------------------------------------------------------------
  210. // Looks up a entry by handle
  211. //-----------------------------------------------------------------------------
  212. template< class T, int HandleBits >
  213. const typename CUtlHandleTable<T, HandleBits>::EntryType_t *CUtlHandleTable<T, HandleBits>::GetEntry( UtlHandle_t handle, bool checkValidity ) const
  214. {
  215. if ( handle == UTLHANDLE_INVALID )
  216. return NULL;
  217. unsigned int nIndex = GetListIndex( handle );
  218. Assert( nIndex < ( unsigned int )m_list.Count() );
  219. if ( nIndex >= ( unsigned int )m_list.Count() )
  220. return NULL;
  221. const EntryType_t &entry = m_list[ nIndex ];
  222. if ( entry.m_nSerial != GetSerialNumber( handle ) )
  223. return NULL;
  224. if ( checkValidity &&
  225. ( 1 == entry.nInvalid ) )
  226. return NULL;
  227. return &entry;
  228. }
  229. template< class T, int HandleBits >
  230. void CUtlHandleTable<T, HandleBits>::MarkHandleInvalid( UtlHandle_t handle )
  231. {
  232. if ( handle == UTLHANDLE_INVALID )
  233. return;
  234. unsigned int nIndex = GetListIndex( handle );
  235. Assert( nIndex < ( unsigned int )m_list.Count() );
  236. if ( nIndex >= ( unsigned int )m_list.Count() )
  237. return;
  238. EntryType_t &entry = m_list[ nIndex ];
  239. if ( entry.m_nSerial != GetSerialNumber( handle ) )
  240. return;
  241. if ( !entry.nInvalid )
  242. {
  243. --m_nValidHandles;
  244. entry.nInvalid = 1;
  245. }
  246. }
  247. template< class T, int HandleBits >
  248. void CUtlHandleTable<T, HandleBits>::MarkHandleValid( UtlHandle_t handle )
  249. {
  250. if ( handle == UTLHANDLE_INVALID )
  251. return;
  252. unsigned int nIndex = GetListIndex( handle );
  253. Assert( nIndex < ( unsigned int )m_list.Count() );
  254. if ( nIndex >= ( unsigned int )m_list.Count() )
  255. return;
  256. EntryType_t &entry = m_list[ nIndex ];
  257. if ( entry.m_nSerial != GetSerialNumber( handle ) )
  258. return;
  259. if ( entry.nInvalid )
  260. {
  261. ++m_nValidHandles;
  262. entry.nInvalid = 0;
  263. }
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Handle wrapper. Assumes 2 things
  267. // 1) That class T has a non-static method called GetHandle which returns a UtlHandle_t
  268. // 2) That class T has a static method called GetPtrFromHandle which returns a T* given a UtlHandle_t
  269. // 3) That class T has a static method called IsHandleValid which accepts a UtlHandle_t
  270. //-----------------------------------------------------------------------------
  271. template< class T >
  272. class CUtlHandle
  273. {
  274. public:
  275. // Constructors
  276. CUtlHandle();
  277. explicit CUtlHandle( T *pObject );
  278. CUtlHandle( UtlHandle_t h );
  279. CUtlHandle( const CUtlHandle<T> &h );
  280. // Assignment
  281. void Set( T *pObject );
  282. void Set( UtlHandle_t h );
  283. const CUtlHandle<T> &operator=( UtlHandle_t h );
  284. const CUtlHandle<T> &operator=( T *pObject );
  285. // Retrieval
  286. T *Get();
  287. const T* Get() const;
  288. // Is the handle valid?
  289. bool IsValid() const;
  290. // Casting
  291. operator T*();
  292. operator UtlHandle_t();
  293. operator bool();
  294. T* operator->();
  295. const T* operator->() const;
  296. // Equality
  297. bool operator==( CUtlHandle<T> h ) const;
  298. bool operator==( T *pObject ) const;
  299. bool operator==( UtlHandle_t h ) const;
  300. bool operator!=( CUtlHandle<T> h ) const;
  301. bool operator!=( T *pObject ) const;
  302. bool operator!=( UtlHandle_t h ) const;
  303. private:
  304. UtlHandle_t m_handle;
  305. };
  306. //-----------------------------------------------------------------------------
  307. // Constructors
  308. //-----------------------------------------------------------------------------
  309. template< class T >
  310. CUtlHandle<T>::CUtlHandle() : m_handle( UTLHANDLE_INVALID )
  311. {
  312. }
  313. template< class T >
  314. CUtlHandle<T>::CUtlHandle( T *pObject )
  315. {
  316. Set( pObject );
  317. }
  318. template< class T >
  319. CUtlHandle<T>::CUtlHandle( UtlHandle_t h )
  320. {
  321. m_handle = h;
  322. }
  323. template< class T >
  324. CUtlHandle<T>::CUtlHandle( const CUtlHandle<T> &h )
  325. {
  326. m_handle = h.m_handle;
  327. }
  328. //-----------------------------------------------------------------------------
  329. // Assignment
  330. //-----------------------------------------------------------------------------
  331. template< class T >
  332. void CUtlHandle<T>::Set( T *pObject )
  333. {
  334. // Assumes T has a member function GetHandle
  335. m_handle = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
  336. }
  337. template< class T >
  338. void CUtlHandle<T>::Set( UtlHandle_t h )
  339. {
  340. m_handle = h;
  341. }
  342. template< class T >
  343. const CUtlHandle<T> &CUtlHandle<T>::operator=( UtlHandle_t h )
  344. {
  345. Set( h );
  346. return *this;
  347. }
  348. template< class T >
  349. const CUtlHandle<T> &CUtlHandle<T>::operator=( T *pObject )
  350. {
  351. Set( pObject );
  352. return *this;
  353. }
  354. //-----------------------------------------------------------------------------
  355. // Is the handle valid?
  356. //-----------------------------------------------------------------------------
  357. template< class T >
  358. bool CUtlHandle<T>::IsValid() const
  359. {
  360. // Assumes T has a static member function IsHandleValid
  361. return T::IsHandleValid( m_handle );
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Retrieval
  365. //-----------------------------------------------------------------------------
  366. template< class T >
  367. T *CUtlHandle<T>::Get()
  368. {
  369. // Assumes T has a static member function GetPtrFromHandle
  370. return T::GetPtrFromHandle( m_handle );
  371. }
  372. template< class T >
  373. const T* CUtlHandle<T>::Get() const
  374. {
  375. // Assumes T has a static member function GetPtrFromHandle
  376. return T::GetPtrFromHandle( m_handle );
  377. }
  378. //-----------------------------------------------------------------------------
  379. // Casting
  380. //-----------------------------------------------------------------------------
  381. template< class T >
  382. CUtlHandle<T>::operator T*()
  383. {
  384. return Get();
  385. }
  386. template< class T >
  387. CUtlHandle<T>::operator UtlHandle_t()
  388. {
  389. return m_handle;
  390. }
  391. template< class T >
  392. T* CUtlHandle<T>::operator->()
  393. {
  394. return Get();
  395. }
  396. template< class T >
  397. const T* CUtlHandle<T>::operator->() const
  398. {
  399. return Get();
  400. }
  401. template< class T >
  402. CUtlHandle<T>::operator bool()
  403. {
  404. return m_handle != UTLHANDLE_INVALID;
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Equality
  408. //-----------------------------------------------------------------------------
  409. template< class T >
  410. bool CUtlHandle<T>::operator==( CUtlHandle<T> h ) const
  411. {
  412. return m_handle == h.m_handle;
  413. }
  414. template< class T >
  415. bool CUtlHandle<T>::operator==( T *pObject ) const
  416. {
  417. UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
  418. return m_handle == h;
  419. }
  420. template< class T >
  421. bool CUtlHandle<T>::operator==( UtlHandle_t h ) const
  422. {
  423. return m_handle == h;
  424. }
  425. template< class T >
  426. bool CUtlHandle<T>::operator!=( CUtlHandle<T> h ) const
  427. {
  428. return m_handle != h.m_handle;
  429. }
  430. template< class T >
  431. bool CUtlHandle<T>::operator!=( T *pObject ) const
  432. {
  433. UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID;
  434. return m_handle != h;
  435. }
  436. template< class T >
  437. bool CUtlHandle<T>::operator!=( UtlHandle_t h ) const
  438. {
  439. return m_handle != h;
  440. }
  441. //-----------------------------------------------------------------------------
  442. // Add this macro to a class definition to hook in handles for it!
  443. //-----------------------------------------------------------------------------
  444. #define DECLARE_HANDLES( _className, _handleBitCount ) \
  445. public: \
  446. UtlHandle_t GetHandle() \
  447. { \
  448. return m_Handle; \
  449. } \
  450. static _className* GetPtrFromHandle( UtlHandle_t h ) \
  451. { \
  452. return m_HandleTable.GetHandle( h ); \
  453. } \
  454. static bool IsHandleValid( UtlHandle_t h ) \
  455. { \
  456. return m_HandleTable.IsHandleValid( h ); \
  457. } \
  458. private: \
  459. UtlHandle_t m_Handle; \
  460. static CUtlHandleTable< _className, _handleBitCount > m_HandleTable
  461. //-----------------------------------------------------------------------------
  462. // Add this macro to a .cpp file to hook in handles for it!
  463. //-----------------------------------------------------------------------------
  464. #define IMPLEMENT_HANDLES( _className, _handleBitCount ) \
  465. CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable;
  466. //-----------------------------------------------------------------------------
  467. // Add these macro to the class constructor + destructor
  468. //-----------------------------------------------------------------------------
  469. #define CONSTRUCT_HANDLE( ) \
  470. m_Handle = m_HandleTable.AddHandle(); \
  471. m_HandleTable.SetHandle( m_Handle, this )
  472. #define DESTRUCT_HANDLE() \
  473. m_HandleTable.RemoveHandle( m_Handle ); \
  474. m_Handle = UTLHANDLE_INVALID
  475. #endif // UTLHANDLETABLE_H