Source code of Windows XP (NT5)
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.

257 lines
5.4 KiB

  1. /*--------------------------------------------------------------------------*
  2. *
  3. * Microsoft Windows
  4. * Copyright (C) Microsoft Corporation, 1992 - 1999
  5. *
  6. * File: refcount.h
  7. *
  8. * Contents: Interface file for reference counting templates
  9. *
  10. * History: 05-Oct-98 jeffro Created
  11. *
  12. *--------------------------------------------------------------------------*/
  13. #ifndef REFCOUNT_H
  14. #define REFCOUNT_H
  15. #pragma once
  16. #include "stddbg.h"
  17. template<class T> class CRefCountedObject;
  18. template<class T> class CRefCountedPtr;
  19. /*+-------------------------------------------------------------------------*
  20. * CRefCountedObject
  21. *
  22. * Template reference-counted object class, intended to be used in
  23. * conjuction with CRefCountedPtr<T>.
  24. *
  25. * Typically, you'd use this like so:
  26. *
  27. * class CClassWithoutRefCounting;
  28. * typedef CRefCountedObject<CClassWithoutRefCounting> CClassWithRefCounting;
  29. *
  30. * CClassWithRefCounting::SmartPtr m_spClass;
  31. * m_spClass.CreateInstance ();
  32. *--------------------------------------------------------------------------*/
  33. template<class BaseClass>
  34. class CRefCountedObject : public BaseClass
  35. {
  36. public:
  37. typedef CRefCountedObject<BaseClass> ThisClass;
  38. typedef CRefCountedPtr<ThisClass> SmartPtr;
  39. CRefCountedObject () : m_cRefs (0) {}
  40. private:
  41. /*
  42. * CRefCountedObject's should only be created on the heap,
  43. * so we'll protect the dtor so it can only be deleted from
  44. * Release, not by automatic object unwinding
  45. */
  46. ~CRefCountedObject () {}
  47. public:
  48. static ThisClass* CreateInstance ()
  49. {
  50. return (new ThisClass);
  51. }
  52. LONG AddRef()
  53. {
  54. return (InterlockedIncrement (&m_cRefs));
  55. }
  56. LONG Release()
  57. {
  58. /*
  59. * if this assert fails, we have mismatched AddRef/Release's
  60. */
  61. ASSERT (m_cRefs > 0);
  62. LONG rc = InterlockedDecrement (&m_cRefs);
  63. if (rc == 0)
  64. delete this;
  65. return (rc);
  66. }
  67. LONG m_cRefs;
  68. private:
  69. /*
  70. * CRefCountedObject's are not meant to be copied or assigned
  71. */
  72. CRefCountedObject (const CRefCountedObject& other); // no impl
  73. CRefCountedObject& operator= (const CRefCountedObject& other); // no impl
  74. };
  75. /*+-------------------------------------------------------------------------*
  76. * CRefCountedPtr
  77. *
  78. * Template reference-counted smart pointer class, intended to be used in
  79. * conjuction with CRefCountedObject<T>.
  80. *
  81. * T must implement CreateInstance, AddRef and Release. It can do this
  82. * intrisically, or use the implementation in CRefCountedObject like this:
  83. *
  84. * class CClassWithoutRefCounting;
  85. * typedef CRefCountedObject<CClassWithoutRefCounting> CClassWithRefCounting;
  86. *--------------------------------------------------------------------------*/
  87. template<class T>
  88. class CRefCountedPtr
  89. {
  90. public:
  91. CRefCountedPtr (T* pRealObject = NULL) :
  92. m_pRealObject (pRealObject)
  93. {
  94. SafeAddRef();
  95. }
  96. CRefCountedPtr (const CRefCountedPtr<T>& other) :
  97. m_pRealObject (other.m_pRealObject)
  98. {
  99. SafeAddRef();
  100. }
  101. ~CRefCountedPtr ()
  102. {
  103. SafeRelease();
  104. }
  105. T* operator->() const
  106. {
  107. return (m_pRealObject);
  108. }
  109. operator T*() const
  110. {
  111. return (m_pRealObject);
  112. }
  113. T& operator*() const
  114. {
  115. return (*m_pRealObject);
  116. }
  117. T** operator&()
  118. {
  119. ASSERT (m_pRealObject == NULL);
  120. return (&m_pRealObject);
  121. }
  122. CRefCountedPtr<T>& operator= (const CRefCountedPtr<T>& other)
  123. {
  124. return (operator= (other.m_pRealObject));
  125. }
  126. CRefCountedPtr<T>& operator= (T* pOtherObject)
  127. {
  128. if (pOtherObject != m_pRealObject)
  129. {
  130. T* pOldObject = m_pRealObject;
  131. m_pRealObject = pOtherObject;
  132. SafeAddRef();
  133. if (pOldObject != NULL)
  134. pOldObject->Release();
  135. }
  136. return (*this);
  137. }
  138. bool CreateInstance()
  139. {
  140. SafeRelease();
  141. m_pRealObject = T::CreateInstance();
  142. if (m_pRealObject == NULL)
  143. return (false);
  144. m_pRealObject->AddRef();
  145. return (true);
  146. }
  147. LONG AddRef()
  148. {
  149. return (SafeAddRef());
  150. }
  151. LONG Release()
  152. {
  153. LONG cRefs = SafeRelease();
  154. m_pRealObject = NULL;
  155. return (cRefs);
  156. }
  157. void Attach(T* pNewObject)
  158. {
  159. if (pNewObject != m_pRealObject)
  160. {
  161. SafeRelease();
  162. m_pRealObject = pNewObject;
  163. }
  164. }
  165. T* Detach()
  166. {
  167. T* pOldObject = m_pRealObject;
  168. m_pRealObject = NULL;
  169. return (pOldObject);
  170. }
  171. bool operator!() const
  172. {
  173. return (m_pRealObject == NULL);
  174. }
  175. bool operator==(const CRefCountedPtr<T>& other)
  176. {
  177. return (m_pRealObject == other.m_pRealObject);
  178. }
  179. bool operator!=(const CRefCountedPtr<T>& other)
  180. {
  181. return (m_pRealObject != other.m_pRealObject);
  182. }
  183. /*
  184. * for comparison to NULL
  185. */
  186. bool operator==(int null) const
  187. {
  188. ASSERT (null == 0);
  189. return (m_pRealObject == NULL);
  190. }
  191. bool operator!=(int null) const
  192. {
  193. ASSERT (null == 0);
  194. return (m_pRealObject != NULL);
  195. }
  196. protected:
  197. LONG SafeAddRef ()
  198. {
  199. return ((m_pRealObject) ? m_pRealObject->AddRef() : 0);
  200. }
  201. LONG SafeRelease ()
  202. {
  203. return ((m_pRealObject) ? m_pRealObject->Release() : -1);
  204. }
  205. protected:
  206. T* m_pRealObject;
  207. };
  208. #endif /* REFCOUNT_H */