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.

258 lines
5.0 KiB

  1. //===== Copyright � 1996-2006, Valve Corporation, All rights reserved. ======//
  2. //
  3. // $Revision: $
  4. // $NoKeywords: $
  5. //===========================================================================//
  6. #ifndef UTLOBJECTREFERENCE_H
  7. #define UTLOBJECTREFERENCE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier1/utlintrusivelist.h"
  12. #include "mathlib/mathlib.h"
  13. #include "tier1/utlvector.h"
  14. // Purpose: class for keeping track of all the references that exist to an object. When the object
  15. // being referenced is freed, all of the references pointing at it will become null.
  16. //
  17. // To Use:
  18. // Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with.
  19. // Replace pointers to that class with CUtlReferences.
  20. // Check these references for null in appropriate places.
  21. //
  22. // NOTE : You can still happily use pointers instead of references where you want to - these
  23. // pointers will not magically become null like references would, but if you know no one is going
  24. // to delete the underlying object during a partcular section of code, it doesn't
  25. // matter. Basically, CUtlReferences don't rely on every use of an object using one.
  26. template<class T> class CUtlReference
  27. {
  28. public:
  29. FORCEINLINE CUtlReference(void)
  30. {
  31. m_pNext = m_pPrev = NULL;
  32. m_pObject = NULL;
  33. }
  34. FORCEINLINE CUtlReference(T *pObj)
  35. {
  36. m_pNext = m_pPrev = NULL;
  37. AddRef( pObj );
  38. }
  39. FORCEINLINE CUtlReference( const CUtlReference<T>& other )
  40. {
  41. CUtlReference();
  42. if ( other.IsValid() )
  43. {
  44. AddRef( (T*)( other.GetObject() ) );
  45. }
  46. }
  47. FORCEINLINE ~CUtlReference(void)
  48. {
  49. KillRef();
  50. }
  51. FORCEINLINE void Set(T *pObj)
  52. {
  53. if ( m_pObject != pObj )
  54. {
  55. KillRef();
  56. AddRef( pObj );
  57. }
  58. }
  59. FORCEINLINE T * operator()(void) const
  60. {
  61. return m_pObject;
  62. }
  63. FORCEINLINE bool IsValid( void) const
  64. {
  65. return ( m_pObject != NULL );
  66. }
  67. FORCEINLINE operator T*()
  68. {
  69. return m_pObject;
  70. }
  71. FORCEINLINE operator const T*() const
  72. {
  73. return m_pObject;
  74. }
  75. FORCEINLINE T * GetObject( void )
  76. {
  77. return m_pObject;
  78. }
  79. FORCEINLINE const T* GetObject( void ) const
  80. {
  81. return m_pObject;
  82. }
  83. FORCEINLINE T* operator->()
  84. {
  85. return m_pObject;
  86. }
  87. FORCEINLINE const T* operator->() const
  88. {
  89. return m_pObject;
  90. }
  91. FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef )
  92. {
  93. Set( otherRef.m_pObject );
  94. return *this;
  95. }
  96. FORCEINLINE CUtlReference &operator=( T *pObj )
  97. {
  98. Set( pObj );
  99. return *this;
  100. }
  101. FORCEINLINE bool operator==( T const *pOther ) const
  102. {
  103. return ( pOther == m_pObject );
  104. }
  105. FORCEINLINE bool operator==( T *pOther ) const
  106. {
  107. return ( pOther == m_pObject );
  108. }
  109. FORCEINLINE bool operator==( const CUtlReference& o ) const
  110. {
  111. return ( o.m_pObject == m_pObject );
  112. }
  113. public:
  114. CUtlReference *m_pNext;
  115. CUtlReference *m_pPrev;
  116. T *m_pObject;
  117. FORCEINLINE void AddRef( T *pObj )
  118. {
  119. m_pObject = pObj;
  120. if ( pObj )
  121. {
  122. pObj->m_References.AddToHead( this );
  123. }
  124. }
  125. FORCEINLINE void KillRef(void)
  126. {
  127. if ( m_pObject )
  128. {
  129. m_pObject->m_References.RemoveNode( this );
  130. m_pObject = NULL;
  131. }
  132. }
  133. };
  134. template<class T> class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference<T> >
  135. {
  136. public:
  137. ~CUtlReferenceList( void )
  138. {
  139. CUtlReference<T> *i = CUtlIntrusiveDList<CUtlReference<T> >::m_pHead;
  140. while( i )
  141. {
  142. CUtlReference<T> *n = i->m_pNext;
  143. i->m_pNext = NULL;
  144. i->m_pPrev = NULL;
  145. i->m_pObject = NULL;
  146. i = n;
  147. }
  148. CUtlIntrusiveDList<CUtlReference<T> >::m_pHead = NULL;
  149. }
  150. };
  151. //-----------------------------------------------------------------------------
  152. // Put this macro in classes that are referenced by CUtlReference
  153. //-----------------------------------------------------------------------------
  154. #define DECLARE_REFERENCED_CLASS( _className ) \
  155. private: \
  156. CUtlReferenceList< _className > m_References; \
  157. template<class T> friend class CUtlReference;
  158. template < class T >
  159. class CUtlReferenceVector : public CUtlBlockVector< CUtlReference< T > >
  160. {
  161. public:
  162. void RemoveAll()
  163. {
  164. for ( int i = 0; i < this->Count(); i++ )
  165. {
  166. this->Element( i ).KillRef();
  167. }
  168. CUtlBlockVector< CUtlReference< T > >::RemoveAll();
  169. }
  170. void FastRemove( int elem )
  171. {
  172. Assert( this->IsValidIndex(elem) );
  173. if ( this->m_Size > 0 )
  174. {
  175. if ( elem != this->m_Size -1 )
  176. {
  177. this->Element( elem ).Set( this->Element( this->m_Size - 1 ).GetObject() );
  178. }
  179. Destruct( &Element( this->m_Size - 1 ) );
  180. --this->m_Size;
  181. }
  182. }
  183. bool FindAndFastRemove( const CUtlReference< T >& src )
  184. {
  185. int elem = Find( src );
  186. if ( elem != -1 )
  187. {
  188. FastRemove( elem );
  189. return true;
  190. }
  191. return false;
  192. }
  193. private:
  194. //
  195. // Disallow methods of CUtlBlockVector that can cause element addresses to change, thus
  196. // breaking assumptions of CUtlReference
  197. //
  198. void Remove( int elem );
  199. bool FindAndRemove( const T& src );
  200. void RemoveMultiple( int elem, int num );
  201. void RemoveMultipleFromHead(int num);
  202. void RemoveMultipleFromTail(int num);
  203. void Swap( CUtlReferenceVector< T > &vec );
  204. void Purge();
  205. void PurgeAndDeleteElements();
  206. void Compact();
  207. };
  208. #endif