smartptr.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // SmartPtr.h
  2. //
  3. // Defines a smart pointer class that does not depend on any ATL headers
  4. #pragma once
  5. ///////////////////////////////////////////////////////////////////////
  6. // Name: AreCOMObjectsEqual [template]
  7. // Desc: Tests two COM pointers for equality.
  8. ///////////////////////////////////////////////////////////////////////
  9. template <class T1, class T2>
  10. bool AreComObjectsEqual(T1 *p1, T2 *p2)
  11. {
  12. bool bResult = false;
  13. if (p1 == NULL && p2 == NULL)
  14. {
  15. // Both are NULL
  16. bResult = true;
  17. }
  18. else if (p1 == NULL || p2 == NULL)
  19. {
  20. // One is NULL and one is not
  21. bResult = false;
  22. }
  23. else
  24. {
  25. // Both are not NULL. Compare IUnknowns.
  26. IUnknown *pUnk1 = NULL;
  27. IUnknown *pUnk2 = NULL;
  28. if (SUCCEEDED(p1->QueryInterface(IID_IUnknown, (void**)&pUnk1)))
  29. {
  30. if (SUCCEEDED(p2->QueryInterface(IID_IUnknown, (void**)&pUnk2)))
  31. {
  32. bResult = (pUnk1 == pUnk2);
  33. pUnk2->Release();
  34. }
  35. pUnk1->Release();
  36. }
  37. }
  38. return bResult;
  39. }
  40. // _NoAddRefOrRelease:
  41. // This is a version of our COM interface that dis-allows AddRef
  42. // and Release. All ref-counting should be done by the SmartPtr
  43. // object, so we want to dis-allow calling AddRef or Release
  44. // directly. The operator-> returns a _NoAddRefOrRelease pointer
  45. // instead of returning the raw COM pointer. (This behavior is the
  46. // same as ATL's CComPtr class.)
  47. template <class T>
  48. class _NoAddRefOrRelease : public T
  49. {
  50. private:
  51. STDMETHOD_(ULONG, AddRef)() = 0;
  52. STDMETHOD_(ULONG, Release)() = 0;
  53. };
  54. template <class T>
  55. class SmartPtr
  56. {
  57. public:
  58. // Ctor
  59. SmartPtr() : m_ptr(NULL)
  60. {
  61. }
  62. // Ctor
  63. SmartPtr(T *ptr)
  64. {
  65. m_ptr = ptr;
  66. if (m_ptr)
  67. {
  68. m_ptr->AddRef();
  69. }
  70. }
  71. // Copy ctor
  72. SmartPtr(const SmartPtr& sptr)
  73. {
  74. m_ptr = sptr.m_ptr;
  75. if (m_ptr)
  76. {
  77. m_ptr->AddRef();
  78. }
  79. }
  80. // Dtor
  81. ~SmartPtr()
  82. {
  83. if (m_ptr)
  84. {
  85. m_ptr->Release();
  86. }
  87. }
  88. // Assignment
  89. SmartPtr& operator=(const SmartPtr& sptr)
  90. {
  91. // Don't do anything if we are assigned to ourselves.
  92. if (!AreComObjectsEqual(m_ptr, sptr.m_ptr))
  93. {
  94. if (m_ptr)
  95. {
  96. m_ptr->Release();
  97. }
  98. m_ptr = sptr.m_ptr;
  99. if (m_ptr)
  100. {
  101. m_ptr->AddRef();
  102. }
  103. }
  104. return *this;
  105. }
  106. // address-of operator
  107. T** operator&()
  108. {
  109. return &m_ptr;
  110. }
  111. // dereference operator
  112. _NoAddRefOrRelease<T>* operator->()
  113. {
  114. return (_NoAddRefOrRelease<T>*)m_ptr;
  115. }
  116. // coerce to underlying pointer type.
  117. operator T*()
  118. {
  119. return m_ptr;
  120. }
  121. // Templated version of QueryInterface
  122. template <class Q> // Q is another interface type
  123. HRESULT QueryInterface(Q **ppQ)
  124. {
  125. return m_ptr->QueryInterface(__uuidof(Q), (void**)ppQ);
  126. }
  127. // safe Release() method
  128. ULONG Release()
  129. {
  130. T *ptr = m_ptr;
  131. ULONG result = 0;
  132. if (ptr)
  133. {
  134. m_ptr = NULL;
  135. result = ptr->Release();
  136. }
  137. return result;
  138. }
  139. // Attach to an existing interface (does not AddRef)
  140. void Attach(T* p)
  141. {
  142. if (m_ptr)
  143. {
  144. m_ptr->Release();
  145. }
  146. m_ptr = p;
  147. }
  148. // Detach the interface (does not Release)
  149. T* Detach()
  150. {
  151. T* p = m_ptr;
  152. m_ptr = NULL;
  153. return p;
  154. }
  155. // equality operator
  156. bool operator==(T *ptr) const
  157. {
  158. return AreComObjectsEqual(m_ptr, ptr);
  159. }
  160. // inequality operator
  161. bool operator!=(T *ptr) const
  162. {
  163. return !operator==(ptr);
  164. }
  165. private:
  166. T *m_ptr;
  167. };