Team Fortress 2 Source Code as on 22/4/2020
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.

165 lines
3.2 KiB

  1. //========= Copyright 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. // Purpose: class for keeping track of all the references that exist to an object. When the object
  14. // being referenced is freed, all of the references pointing at it will become null.
  15. //
  16. // To Use:
  17. // Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with.
  18. // Replace pointers to that class with CUtlReferences.
  19. // Check these references for null in appropriate places.
  20. //
  21. // NOTE : You can still happily use pointers instead of references where you want to - these
  22. // pointers will not magically become null like references would, but if you know no one is going
  23. // to delete the underlying object during a partcular section of code, it doesn't
  24. // matter. Basically, CUtlReferences don't rely on every use of an object using one.
  25. template<class T> class CUtlReference
  26. {
  27. public:
  28. FORCEINLINE CUtlReference(void)
  29. {
  30. m_pNext = m_pPrev = NULL;
  31. m_pObject = NULL;
  32. }
  33. FORCEINLINE CUtlReference(T *pObj)
  34. {
  35. m_pNext = m_pPrev = NULL;
  36. AddRef( pObj );
  37. }
  38. FORCEINLINE ~CUtlReference(void)
  39. {
  40. KillRef();
  41. }
  42. FORCEINLINE void Set(T *pObj)
  43. {
  44. if ( m_pObject != pObj )
  45. {
  46. KillRef();
  47. AddRef( pObj );
  48. }
  49. }
  50. FORCEINLINE T * operator()(void) const
  51. {
  52. return m_pObject;
  53. }
  54. FORCEINLINE operator T*()
  55. {
  56. return m_pObject;
  57. }
  58. FORCEINLINE operator const T*() const
  59. {
  60. return m_pObject;
  61. }
  62. FORCEINLINE T* operator->()
  63. {
  64. return m_pObject;
  65. }
  66. FORCEINLINE const T* operator->() const
  67. {
  68. return m_pObject;
  69. }
  70. FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef )
  71. {
  72. Set( otherRef.m_pObject );
  73. return *this;
  74. }
  75. FORCEINLINE CUtlReference &operator=( T *pObj )
  76. {
  77. Set( pObj );
  78. return *this;
  79. }
  80. FORCEINLINE bool operator==( const CUtlReference& o ) const
  81. {
  82. return ( o.m_pObject == m_pObject );
  83. }
  84. public:
  85. CUtlReference *m_pNext;
  86. CUtlReference *m_pPrev;
  87. T *m_pObject;
  88. FORCEINLINE void AddRef( T *pObj )
  89. {
  90. m_pObject = pObj;
  91. if ( pObj )
  92. {
  93. pObj->m_References.AddToHead( this );
  94. }
  95. }
  96. FORCEINLINE void KillRef(void)
  97. {
  98. if ( m_pObject )
  99. {
  100. m_pObject->m_References.RemoveNode( this );
  101. m_pObject = NULL;
  102. }
  103. }
  104. };
  105. template<class T> class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference<T> >
  106. {
  107. public:
  108. ~CUtlReferenceList( void )
  109. {
  110. CUtlReference<T> *i = CUtlIntrusiveDList<CUtlReference<T> >::m_pHead;
  111. while( i )
  112. {
  113. CUtlReference<T> *n = i->m_pNext;
  114. i->m_pNext = NULL;
  115. i->m_pPrev = NULL;
  116. i->m_pObject = NULL;
  117. i = n;
  118. }
  119. CUtlIntrusiveDList<CUtlReference<T> >::m_pHead = NULL;
  120. }
  121. };
  122. //-----------------------------------------------------------------------------
  123. // Put this macro in classes that are referenced by CUtlReference
  124. //-----------------------------------------------------------------------------
  125. #define DECLARE_REFERENCED_CLASS( _className ) \
  126. private: \
  127. CUtlReferenceList< _className > m_References; \
  128. template<class T> friend class CUtlReference;
  129. #endif