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.

260 lines
7.5 KiB

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