intrusive_ptr.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp
  4. //
  5. // (C) Copyright Peter Dimov 2001, 2002
  6. // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
  7. // Software License, Version 1.0. (See accompanying file
  8. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See http://www.boost.org/libs/interprocess for documentation.
  11. //
  12. //////////////////////////////////////////////////////////////////////////////
  13. #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED
  14. #define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED
  15. //!\file
  16. //!Describes an intrusive ownership pointer.
  17. #include <boost/interprocess/detail/config_begin.hpp>
  18. #include <boost/interprocess/detail/workaround.hpp>
  19. #include <boost/assert.hpp>
  20. #include <boost/interprocess/detail/utilities.hpp>
  21. #include <boost/intrusive/pointer_traits.hpp>
  22. #include <functional> // for std::less
  23. #include <iosfwd> // for std::basic_ostream
  24. namespace boost {
  25. namespace interprocess {
  26. //!The intrusive_ptr class template stores a pointer to an object
  27. //!with an embedded reference count. intrusive_ptr is parameterized on
  28. //!T (the type of the object pointed to) and VoidPointer(a void pointer type
  29. //!that defines the type of pointer that intrusive_ptr will store).
  30. //!intrusive_ptr<T, void *> defines a class with a T* member whereas
  31. //!intrusive_ptr<T, offset_ptr<void> > defines a class with a offset_ptr<T> member.
  32. //!Relies on unqualified calls to:
  33. //!
  34. //! void intrusive_ptr_add_ref(T * p);
  35. //! void intrusive_ptr_release(T * p);
  36. //!
  37. //! with (p != 0)
  38. //!
  39. //!The object is responsible for destroying itself.
  40. template<class T, class VoidPointer>
  41. class intrusive_ptr
  42. {
  43. public:
  44. //!Provides the type of the internal stored pointer.
  45. typedef typename boost::intrusive::
  46. pointer_traits<VoidPointer>::template
  47. rebind_pointer<T>::type pointer;
  48. //!Provides the type of the stored pointer.
  49. typedef T element_type;
  50. /// @cond
  51. private:
  52. typedef VoidPointer VP;
  53. typedef intrusive_ptr this_type;
  54. typedef pointer this_type::*unspecified_bool_type;
  55. /// @endcond
  56. public:
  57. //!Constructor. Initializes internal pointer to 0.
  58. //!Does not throw
  59. intrusive_ptr(): m_ptr(0)
  60. {}
  61. //!Constructor. Copies pointer and if "p" is not zero and
  62. //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)).
  63. //!Does not throw
  64. intrusive_ptr(const pointer &p, bool add_ref = true): m_ptr(p)
  65. {
  66. if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  67. }
  68. //!Copy constructor. Copies the internal pointer and if "p" is not
  69. //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw
  70. intrusive_ptr(intrusive_ptr const & rhs)
  71. : m_ptr(rhs.m_ptr)
  72. {
  73. if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  74. }
  75. //!Constructor from related. Copies the internal pointer and if "p" is not
  76. //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw
  77. template<class U> intrusive_ptr
  78. (intrusive_ptr<U, VP> const & rhs)
  79. : m_ptr(rhs.get())
  80. {
  81. if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  82. }
  83. //!Destructor. If internal pointer is not 0, calls
  84. //!intrusive_ptr_release(to_raw_pointer(m_ptr)). Does not throw
  85. ~intrusive_ptr()
  86. {
  87. if(m_ptr != 0) intrusive_ptr_release(ipcdetail::to_raw_pointer(m_ptr));
  88. }
  89. //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this).
  90. //!Does not throw
  91. intrusive_ptr & operator=(intrusive_ptr const & rhs)
  92. {
  93. this_type(rhs).swap(*this);
  94. return *this;
  95. }
  96. //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this).
  97. //!Does not throw
  98. template<class U> intrusive_ptr & operator=
  99. (intrusive_ptr<U, VP> const & rhs)
  100. {
  101. this_type(rhs).swap(*this);
  102. return *this;
  103. }
  104. //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this).
  105. //!Does not throw
  106. intrusive_ptr & operator=(pointer rhs)
  107. {
  108. this_type(rhs).swap(*this);
  109. return *this;
  110. }
  111. //!Returns a reference to the internal pointer.
  112. //!Does not throw
  113. pointer &get()
  114. { return m_ptr; }
  115. //!Returns a reference to the internal pointer.
  116. //!Does not throw
  117. const pointer &get() const
  118. { return m_ptr; }
  119. //!Returns *get().
  120. //!Does not throw
  121. T & operator*() const
  122. { return *m_ptr; }
  123. //!Returns *get().
  124. //!Does not throw
  125. const pointer &operator->() const
  126. { return m_ptr; }
  127. //!Returns get().
  128. //!Does not throw
  129. pointer &operator->()
  130. { return m_ptr; }
  131. //!Conversion to boolean.
  132. //!Does not throw
  133. operator unspecified_bool_type () const
  134. { return m_ptr == 0? 0: &this_type::m_ptr; }
  135. //!Not operator.
  136. //!Does not throw
  137. bool operator! () const
  138. { return m_ptr == 0; }
  139. //!Exchanges the contents of the two smart pointers.
  140. //!Does not throw
  141. void swap(intrusive_ptr & rhs)
  142. { ipcdetail::do_swap(m_ptr, rhs.m_ptr); }
  143. /// @cond
  144. private:
  145. pointer m_ptr;
  146. /// @endcond
  147. };
  148. //!Returns a.get() == b.get().
  149. //!Does not throw
  150. template<class T, class U, class VP> inline
  151. bool operator==(intrusive_ptr<T, VP> const & a,
  152. intrusive_ptr<U, VP> const & b)
  153. { return a.get() == b.get(); }
  154. //!Returns a.get() != b.get().
  155. //!Does not throw
  156. template<class T, class U, class VP> inline
  157. bool operator!=(intrusive_ptr<T, VP> const & a,
  158. intrusive_ptr<U, VP> const & b)
  159. { return a.get() != b.get(); }
  160. //!Returns a.get() == b.
  161. //!Does not throw
  162. template<class T, class VP> inline
  163. bool operator==(intrusive_ptr<T, VP> const & a,
  164. const typename intrusive_ptr<T, VP>::pointer &b)
  165. { return a.get() == b; }
  166. //!Returns a.get() != b.
  167. //!Does not throw
  168. template<class T, class VP> inline
  169. bool operator!=(intrusive_ptr<T, VP> const & a,
  170. const typename intrusive_ptr<T, VP>::pointer &b)
  171. { return a.get() != b; }
  172. //!Returns a == b.get().
  173. //!Does not throw
  174. template<class T, class VP> inline
  175. bool operator==(const typename intrusive_ptr<T, VP>::pointer &a,
  176. intrusive_ptr<T, VP> const & b)
  177. { return a == b.get(); }
  178. //!Returns a != b.get().
  179. //!Does not throw
  180. template<class T, class VP> inline
  181. bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a,
  182. intrusive_ptr<T, VP> const & b)
  183. { return a != b.get(); }
  184. //!Returns a.get() < b.get().
  185. //!Does not throw
  186. template<class T, class VP> inline
  187. bool operator<(intrusive_ptr<T, VP> const & a,
  188. intrusive_ptr<T, VP> const & b)
  189. {
  190. return std::less<typename intrusive_ptr<T, VP>::pointer>()
  191. (a.get(), b.get());
  192. }
  193. //!Exchanges the contents of the two intrusive_ptrs.
  194. //!Does not throw
  195. template<class T, class VP> inline
  196. void swap(intrusive_ptr<T, VP> & lhs,
  197. intrusive_ptr<T, VP> & rhs)
  198. { lhs.swap(rhs); }
  199. // operator<<
  200. template<class E, class T, class Y, class VP>
  201. inline std::basic_ostream<E, T> & operator<<
  202. (std::basic_ostream<E, T> & os, intrusive_ptr<Y, VP> const & p)
  203. { os << p.get(); return os; }
  204. //!Returns p.get().
  205. //!Does not throw
  206. template<class T, class VP>
  207. inline typename boost::interprocess::intrusive_ptr<T, VP>::pointer
  208. to_raw_pointer(intrusive_ptr<T, VP> p)
  209. { return p.get(); }
  210. /*Emulates static cast operator. Does not throw*/
  211. /*
  212. template<class T, class U, class VP>
  213. inline boost::interprocess::intrusive_ptr<T, VP> static_pointer_cast
  214. (boost::interprocess::intrusive_ptr<U, VP> const & p)
  215. { return do_static_cast<U>(p.get()); }
  216. */
  217. /*Emulates const cast operator. Does not throw*/
  218. /*
  219. template<class T, class U, class VP>
  220. inline boost::interprocess::intrusive_ptr<T, VP> const_pointer_cast
  221. (boost::interprocess::intrusive_ptr<U, VP> const & p)
  222. { return do_const_cast<U>(p.get()); }
  223. */
  224. /*Emulates dynamic cast operator. Does not throw*/
  225. /*
  226. template<class T, class U, class VP>
  227. inline boost::interprocess::intrusive_ptr<T, VP> dynamic_pointer_cast
  228. (boost::interprocess::intrusive_ptr<U, VP> const & p)
  229. { return do_dynamic_cast<U>(p.get()); }
  230. */
  231. /*Emulates reinterpret cast operator. Does not throw*/
  232. /*
  233. template<class T, class U, class VP>
  234. inline boost::interprocess::intrusive_ptr<T, VP>reinterpret_pointer_cast
  235. (boost::interprocess::intrusive_ptr<U, VP> const & p)
  236. { return do_reinterpret_cast<U>(p.get()); }
  237. */
  238. } // namespace interprocess
  239. /// @cond
  240. #if defined(_MSC_VER) && (_MSC_VER < 1400)
  241. //!Returns p.get().
  242. //!Does not throw
  243. template<class T, class VP>
  244. inline T *to_raw_pointer(boost::interprocess::intrusive_ptr<T, VP> p)
  245. { return p.get(); }
  246. #endif
  247. /// @endcond
  248. } // namespace boost
  249. #include <boost/interprocess/detail/config_end.hpp>
  250. #endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED