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.

243 lines
6.4 KiB

  1. // slbRCPtr.h -- Reference counting smart pointer.
  2. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  3. // 1999. This computer program includes Confidential, Proprietary
  4. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  5. // use, disclosure, and/or reproduction is prohibited unless authorized
  6. // in writing. All Rights Reserved.
  7. #if !defined(SLB_RCPTR_H)
  8. #define SLB_RCPTR_H
  9. #include "slbRCComp.h"
  10. #include "slbRCObj.h"
  11. namespace slbRefCnt {
  12. // template class RCPtr -- Reference Counting Pointer
  13. //
  14. // The RCPtr template implements a variant of the "Counted Pointer"
  15. // idiom. RCPtr is a reference counting smart pointer-to-T object
  16. // where T must inherit from RCObject (reference counted objects, see
  17. // slbRCObj.h).
  18. //
  19. // C is the comparator class to use in performing the pointer
  20. // comparison operations, defaulting to ShallowComparator. See
  21. // slbRComp.h for more information.
  22. //
  23. // The template's original design was inspired by the reference
  24. // counting idiom described by Item #29 in the book "More Effective
  25. // C++," Scott Meyers, Addison-Wesley, 1996.
  26. //
  27. // CONTRAINTS: RCPtr can only be used for reference counting those
  28. // objects for which you have the source because RCPtr only reference
  29. // objects derived from RCObject. See GRCPtr in slbGRCPtr.h for
  30. // reference counting objects when you don't have access to the source
  31. // of the class to reference count.
  32. //
  33. // RCPtr should not be used as a base class.
  34. //
  35. // CAVEATS: The client should not use the Dummy * conversion
  36. // operator. The definition allows smart pointer comparisons. See
  37. // slbRCComp.h for more information.
  38. template<class T, typename C = ShallowComparator<T> >
  39. class RCPtr
  40. {
  41. public:
  42. // Types
  43. typedef T ValueType;
  44. // PrivateDummy is a helper class to support validity testing of a
  45. // pointer. This class together with the conversion operator
  46. // PrivateDummy const *() below allows smart pointers to be tested
  47. // for nullness (validity tests). In other words, comparing
  48. // pointers in a syntactically natural way without allowing
  49. // heterogeneous comparisons and that won't violate the
  50. // protections that RCPtr provides. The technique is from an
  51. // article by Don Box in "Com Smart Pointers Also Considered
  52. // Harmful," 1996, C++ Report.
  53. //
  54. // CAVEAT: There is a defect in the at least with MSVC++ 6.0 where
  55. // constructs testing the pointer for nullness will fail to
  56. // compile with a error message in the Release configuration but
  57. // compile successfully in Debug. For example,
  58. //
  59. // if (p) ...
  60. //
  61. // where p is an RCPtr or GRCPtr may fail to compile in the
  62. // Release configuration.
  63. //
  64. // CAVEAT: Although the PrivateDummy and the conversion operator
  65. // has public access to the pointer of the object being counted
  66. // (RCObject *), a C-style or reinterpret_cast cast would have to
  67. // be used. As in all cases using those cast
  68. // constructs--programmer beware.
  69. //
  70. // DESIGN NOTE: The helper class is functionally the same as the
  71. // one in the RCPtr template. In a previous release, this dummy
  72. // class was made into a template and shared with both RCPtr and
  73. // GRCPtr. However, casual compilation tests with MSVC++ 6.0 indicate
  74. // compilation with a dummy local to each class resulted in
  75. // noticable faster compilations using a test suite. Rather than
  76. // suffer repeatedly slower compilations, the helper was made
  77. // local to each user.
  78. class PrivateDummy
  79. {};
  80. // Constructors/Destructors
  81. RCPtr(T *pReal = 0);
  82. RCPtr(RCPtr<T, C> const &rhs);
  83. ~RCPtr();
  84. // Operators
  85. RCPtr<T, C> &operator=(RCPtr<T, C> const &rhs);
  86. // Enable validity test of RCPtr. See the explanation in
  87. // slbRCComp.h.
  88. operator PrivateDummy const *() const
  89. { return reinterpret_cast<PrivateDummy *>(m_pointee); }
  90. // Access
  91. T *operator->() const;
  92. T &operator*() const;
  93. private:
  94. // Operations
  95. void Init();
  96. // Variables
  97. T *m_pointee;
  98. };
  99. template<class T, typename C>
  100. RCPtr<T, C>::RCPtr(T *pReal)
  101. : m_pointee(pReal)
  102. {
  103. Init();
  104. }
  105. template<class T, typename C>
  106. RCPtr<T, C>::RCPtr(RCPtr<T, C> const &rhs)
  107. : m_pointee(rhs.m_pointee)
  108. {
  109. Init();
  110. }
  111. template<class T, typename C>
  112. RCPtr<T, C>::~RCPtr()
  113. {
  114. try
  115. {
  116. if (m_pointee)
  117. m_pointee->RemoveReference();
  118. }
  119. catch (...)
  120. {
  121. // don't allow exceptions to propagate out of destructor
  122. }
  123. }
  124. template<class T, typename C>
  125. RCPtr<T, C> &
  126. RCPtr<T, C>::operator=(RCPtr<T, C> const &rhs)
  127. {
  128. if (m_pointee != rhs.m_pointee)
  129. {
  130. if (m_pointee)
  131. m_pointee->RemoveReference();
  132. m_pointee = rhs.m_pointee;
  133. Init();
  134. }
  135. return *this;
  136. }
  137. template<class T, typename C>
  138. T *
  139. RCPtr<T, C>::operator->() const
  140. {
  141. return m_pointee;
  142. }
  143. template<class T, typename C>
  144. T &
  145. RCPtr<T, C>::operator*() const
  146. {
  147. return *m_pointee;
  148. }
  149. template<class T, typename C>
  150. bool
  151. operator==(RCPtr<T, C> const &lhs,
  152. RCPtr<T, C> const &rhs)
  153. {
  154. C Comp;
  155. return Comp.Equates(lhs.operator->(), rhs.operator->());
  156. }
  157. template<class T, typename C>
  158. bool
  159. operator!=(RCPtr<T, C> const &lhs,
  160. RCPtr<T, C> const &rhs)
  161. {
  162. C Comp;
  163. return !Comp.Equates(lhs.operator->(), rhs.operator->());
  164. }
  165. template<class T, typename C>
  166. bool
  167. operator<(RCPtr<T, C> const &lhs,
  168. RCPtr<T, C> const &rhs)
  169. {
  170. C Comp;
  171. return Comp.IsLess(lhs.operator->(), rhs.operator->());
  172. }
  173. template<class T, typename C>
  174. bool
  175. operator>(RCPtr<T, C> const &lhs,
  176. RCPtr<T, C> const &rhs)
  177. {
  178. C Comp;
  179. return Comp.IsLess(rhs.operator->(), lhs.operator->());
  180. }
  181. template<class T, typename C>
  182. bool
  183. operator<=(RCPtr<T, C> const &lhs,
  184. RCPtr<T, C> const &rhs)
  185. {
  186. C Comp;
  187. return !Comp.IsLess(rhs.operator->(), lhs.operator->());
  188. }
  189. template<class T, typename C>
  190. bool
  191. operator>=(RCPtr<T, C> const &lhs,
  192. RCPtr<T, C> const &rhs)
  193. {
  194. C Comp;
  195. return !Comp.IsLess(lhs.operator->(), rhs.operator->());
  196. }
  197. template<class T, typename C>
  198. void
  199. RCPtr<T, C>::Init()
  200. {
  201. if (m_pointee)
  202. m_pointee->AddReference();
  203. }
  204. } // namespace
  205. #endif // SLB_RCPTR_H