intrusive_ptr.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. #ifndef BOOST_CONFIG_HPP
  16. # include <boost/config.hpp>
  17. #endif
  18. #
  19. #if defined(BOOST_HAS_PRAGMA_ONCE)
  20. # pragma once
  21. #endif
  22. //!\file
  23. //!Describes an intrusive ownership pointer.
  24. #include <boost/interprocess/detail/config_begin.hpp>
  25. #include <boost/interprocess/detail/workaround.hpp>
  26. #include <boost/assert.hpp>
  27. #include <boost/interprocess/detail/utilities.hpp>
  28. #include <boost/intrusive/pointer_traits.hpp>
  29. #include <boost/move/adl_move_swap.hpp>
  30. #include <boost/move/core.hpp>
  31. #include <iosfwd> // for std::basic_ostream
  32. #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less
  33. namespace boost {
  34. namespace interprocess {
  35. //!The intrusive_ptr class template stores a pointer to an object
  36. //!with an embedded reference count. intrusive_ptr is parameterized on
  37. //!T (the type of the object pointed to) and VoidPointer(a void pointer type
  38. //!that defines the type of pointer that intrusive_ptr will store).
  39. //!intrusive_ptr<T, void *> defines a class with a T* member whereas
  40. //!intrusive_ptr<T, offset_ptr<void> > defines a class with a offset_ptr<T> member.
  41. //!Relies on unqualified calls to:
  42. //!
  43. //! void intrusive_ptr_add_ref(T * p) BOOST_NOEXCEPT;
  44. //! void intrusive_ptr_release(T * p) BOOST_NOEXCEPT;
  45. //!
  46. //! with (p != 0)
  47. //!
  48. //!The object is responsible for destroying itself.
  49. template<class T, class VoidPointer>
  50. class intrusive_ptr
  51. {
  52. public:
  53. //!Provides the type of the internal stored pointer.
  54. typedef typename boost::intrusive::
  55. pointer_traits<VoidPointer>::template
  56. rebind_pointer<T>::type pointer;
  57. //!Provides the type of the stored pointer.
  58. typedef T element_type;
  59. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  60. private:
  61. typedef VoidPointer VP;
  62. typedef intrusive_ptr this_type;
  63. typedef pointer this_type::*unspecified_bool_type;
  64. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  65. BOOST_COPYABLE_AND_MOVABLE(intrusive_ptr)
  66. public:
  67. //!Constructor. Initializes internal pointer to 0.
  68. //!Does not throw
  69. intrusive_ptr() BOOST_NOEXCEPT
  70. : m_ptr(0)
  71. {}
  72. //!Constructor. Copies pointer and if "p" is not zero and
  73. //!"add_ref" is true calls intrusive_ptr_add_ref(to_raw_pointer(p)).
  74. //!Does not throw
  75. intrusive_ptr(const pointer &p, bool add_ref = true) BOOST_NOEXCEPT
  76. : m_ptr(p)
  77. {
  78. if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  79. }
  80. //!Copy constructor. Copies the internal pointer and if "p" is not
  81. //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw
  82. intrusive_ptr(intrusive_ptr const & rhs) BOOST_NOEXCEPT
  83. : m_ptr(rhs.m_ptr)
  84. {
  85. if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  86. }
  87. //!Move constructor. Moves the internal pointer. Does not throw
  88. intrusive_ptr(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT
  89. : m_ptr(rhs.m_ptr)
  90. {
  91. rhs.m_ptr = 0;
  92. }
  93. //!Constructor from related. Copies the internal pointer and if "p" is not
  94. //!zero calls intrusive_ptr_add_ref(to_raw_pointer(p)). Does not throw
  95. template<class U> intrusive_ptr(intrusive_ptr<U, VP> const & rhs) BOOST_NOEXCEPT
  96. : m_ptr(rhs.get())
  97. {
  98. if(m_ptr != 0) intrusive_ptr_add_ref(ipcdetail::to_raw_pointer(m_ptr));
  99. }
  100. //!Destructor. Calls reset(). Does not throw
  101. ~intrusive_ptr()
  102. {
  103. reset();
  104. }
  105. //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this).
  106. //!Does not throw
  107. intrusive_ptr & operator=(BOOST_COPY_ASSIGN_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT
  108. {
  109. this_type(rhs).swap(*this);
  110. return *this;
  111. }
  112. //!Move Assignment operator
  113. //!Does not throw
  114. intrusive_ptr & operator=(BOOST_RV_REF(intrusive_ptr) rhs) BOOST_NOEXCEPT
  115. {
  116. rhs.swap(*this);
  117. rhs.reset();
  118. return *this;
  119. }
  120. //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this).
  121. //!Does not throw
  122. template<class U> intrusive_ptr & operator=(intrusive_ptr<U, VP> const & rhs) BOOST_NOEXCEPT
  123. {
  124. this_type(rhs).swap(*this);
  125. return *this;
  126. }
  127. //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this).
  128. //!Does not throw
  129. intrusive_ptr & operator=(pointer rhs) BOOST_NOEXCEPT
  130. {
  131. this_type(rhs).swap(*this);
  132. return *this;
  133. }
  134. //!Release internal pointer and set it to 0. If internal pointer is not 0, calls
  135. //!intrusive_ptr_release(to_raw_pointer(m_ptr)). Does not throw
  136. void reset() BOOST_NOEXCEPT {
  137. if(m_ptr != 0) {
  138. pointer ptr = m_ptr;
  139. m_ptr = 0;
  140. intrusive_ptr_release(ipcdetail::to_raw_pointer(ptr));
  141. }
  142. }
  143. //!Returns a reference to the internal pointer.
  144. //!Does not throw
  145. pointer &get() BOOST_NOEXCEPT
  146. { return m_ptr; }
  147. //!Returns a reference to the internal pointer.
  148. //!Does not throw
  149. const pointer &get() const BOOST_NOEXCEPT
  150. { return m_ptr; }
  151. //!Returns *get().
  152. //!Does not throw
  153. T & operator*() const BOOST_NOEXCEPT
  154. { return *m_ptr; }
  155. //!Returns *get().
  156. //!Does not throw
  157. const pointer &operator->() const BOOST_NOEXCEPT
  158. { return m_ptr; }
  159. //!Returns get().
  160. //!Does not throw
  161. pointer &operator->() BOOST_NOEXCEPT
  162. { return m_ptr; }
  163. //!Conversion to boolean.
  164. //!Does not throw
  165. operator unspecified_bool_type () const BOOST_NOEXCEPT
  166. { return m_ptr == 0? 0: &this_type::m_ptr; }
  167. //!Not operator.
  168. //!Does not throw
  169. bool operator! () const BOOST_NOEXCEPT
  170. { return m_ptr == 0; }
  171. //!Exchanges the contents of the two smart pointers.
  172. //!Does not throw
  173. void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
  174. { ::boost::adl_move_swap(m_ptr, rhs.m_ptr); }
  175. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  176. private:
  177. pointer m_ptr;
  178. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  179. };
  180. //!Returns a.get() == b.get().
  181. //!Does not throw
  182. template<class T, class U, class VP> inline
  183. bool operator==(intrusive_ptr<T, VP> const & a,
  184. intrusive_ptr<U, VP> const & b) BOOST_NOEXCEPT
  185. { return a.get() == b.get(); }
  186. //!Returns a.get() != b.get().
  187. //!Does not throw
  188. template<class T, class U, class VP> inline
  189. bool operator!=(intrusive_ptr<T, VP> const & a,
  190. intrusive_ptr<U, VP> const & b) BOOST_NOEXCEPT
  191. { return a.get() != b.get(); }
  192. //!Returns a.get() == b.
  193. //!Does not throw
  194. template<class T, class VP> inline
  195. bool operator==(intrusive_ptr<T, VP> const & a,
  196. const typename intrusive_ptr<T, VP>::pointer &b) BOOST_NOEXCEPT
  197. { return a.get() == b; }
  198. //!Returns a.get() != b.
  199. //!Does not throw
  200. template<class T, class VP> inline
  201. bool operator!=(intrusive_ptr<T, VP> const & a,
  202. const typename intrusive_ptr<T, VP>::pointer &b) BOOST_NOEXCEPT
  203. { return a.get() != b; }
  204. //!Returns a == b.get().
  205. //!Does not throw
  206. template<class T, class VP> inline
  207. bool operator==(const typename intrusive_ptr<T, VP>::pointer &a,
  208. intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT
  209. { return a == b.get(); }
  210. //!Returns a != b.get().
  211. //!Does not throw
  212. template<class T, class VP> inline
  213. bool operator!=(const typename intrusive_ptr<T, VP>::pointer &a,
  214. intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT
  215. { return a != b.get(); }
  216. //!Returns a.get() < b.get().
  217. //!Does not throw
  218. template<class T, class VP> inline
  219. bool operator<(intrusive_ptr<T, VP> const & a,
  220. intrusive_ptr<T, VP> const & b) BOOST_NOEXCEPT
  221. {
  222. return std::less<typename intrusive_ptr<T, VP>::pointer>()
  223. (a.get(), b.get());
  224. }
  225. //!Exchanges the contents of the two intrusive_ptrs.
  226. //!Does not throw
  227. template<class T, class VP> inline
  228. void swap(intrusive_ptr<T, VP> & lhs,
  229. intrusive_ptr<T, VP> & rhs) BOOST_NOEXCEPT
  230. { lhs.swap(rhs); }
  231. // operator<<
  232. template<class E, class T, class Y, class VP>
  233. inline std::basic_ostream<E, T> & operator<<
  234. (std::basic_ostream<E, T> & os, intrusive_ptr<Y, VP> const & p) BOOST_NOEXCEPT
  235. { os << p.get(); return os; }
  236. //!Returns p.get().
  237. //!Does not throw
  238. template<class T, class VP>
  239. inline typename boost::interprocess::intrusive_ptr<T, VP>::pointer
  240. to_raw_pointer(intrusive_ptr<T, VP> p) BOOST_NOEXCEPT
  241. { return p.get(); }
  242. /*Emulates static cast operator. Does not throw*/
  243. /*
  244. template<class T, class U, class VP>
  245. inline boost::interprocess::intrusive_ptr<T, VP> static_pointer_cast
  246. (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT
  247. { return do_static_cast<U>(p.get()); }
  248. */
  249. /*Emulates const cast operator. Does not throw*/
  250. /*
  251. template<class T, class U, class VP>
  252. inline boost::interprocess::intrusive_ptr<T, VP> const_pointer_cast
  253. (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT
  254. { return do_const_cast<U>(p.get()); }
  255. */
  256. /*Emulates dynamic cast operator. Does not throw*/
  257. /*
  258. template<class T, class U, class VP>
  259. inline boost::interprocess::intrusive_ptr<T, VP> dynamic_pointer_cast
  260. (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT
  261. { return do_dynamic_cast<U>(p.get()); }
  262. */
  263. /*Emulates reinterpret cast operator. Does not throw*/
  264. /*
  265. template<class T, class U, class VP>
  266. inline boost::interprocess::intrusive_ptr<T, VP>reinterpret_pointer_cast
  267. (boost::interprocess::intrusive_ptr<U, VP> const & p) BOOST_NOEXCEPT
  268. { return do_reinterpret_cast<U>(p.get()); }
  269. */
  270. } // namespace interprocess
  271. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  272. #if defined(_MSC_VER) && (_MSC_VER < 1400)
  273. //!Returns p.get().
  274. //!Does not throw
  275. template<class T, class VP>
  276. inline T *to_raw_pointer(boost::interprocess::intrusive_ptr<T, VP> p) BOOST_NOEXCEPT
  277. { return p.get(); }
  278. #endif
  279. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  280. } // namespace boost
  281. #include <boost/interprocess/detail/config_end.hpp>
  282. #endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED