shared_ptr.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // This file is the adaptation for Interprocess of boost/shared_ptr.hpp
  4. //
  5. // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
  6. // (C) Copyright Peter Dimov 2001, 2002, 2003
  7. // (C) Copyright Ion Gaztanaga 2006-2012.
  8. // Distributed under the Boost Software License, Version 1.0.
  9. // (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // See http://www.boost.org/libs/interprocess for documentation.
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
  16. #define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED
  17. #ifndef BOOST_CONFIG_HPP
  18. # include <boost/config.hpp>
  19. #endif
  20. #
  21. #if defined(BOOST_HAS_PRAGMA_ONCE)
  22. # pragma once
  23. #endif
  24. #include <boost/interprocess/detail/config_begin.hpp>
  25. #include <boost/interprocess/detail/workaround.hpp>
  26. #include <boost/interprocess/detail/utilities.hpp>
  27. #include <boost/interprocess/detail/cast_tags.hpp>
  28. #include <boost/assert.hpp>
  29. #include <boost/interprocess/smart_ptr/detail/shared_count.hpp>
  30. #include <boost/interprocess/detail/mpl.hpp>
  31. #include <boost/interprocess/detail/nothrow.hpp>
  32. #include <boost/move/utility_core.hpp>
  33. #include <boost/interprocess/detail/type_traits.hpp>
  34. #include <boost/interprocess/allocators/allocator.hpp>
  35. #include <boost/interprocess/smart_ptr/deleter.hpp>
  36. #include <boost/intrusive/pointer_traits.hpp>
  37. #include <iosfwd> // for std::basic_ostream
  38. //!\file
  39. //!Describes the smart pointer shared_ptr
  40. namespace boost{
  41. namespace interprocess{
  42. template<class T, class VoidAllocator, class Deleter> class weak_ptr;
  43. template<class T, class VoidAllocator, class Deleter> class enable_shared_from_this;
  44. namespace ipcdetail{
  45. template<class T, class VoidAllocator, class Deleter>
  46. inline void sp_enable_shared_from_this
  47. (shared_count<T, VoidAllocator, Deleter> const & pn
  48. ,enable_shared_from_this<T, VoidAllocator, Deleter> const*pe
  49. ,T *ptr)
  50. {
  51. (void)ptr;
  52. if(pe != 0){
  53. pe->_internal_weak_this._internal_assign(pn);
  54. }
  55. }
  56. template<class T, class VoidAllocator, class Deleter>
  57. inline void sp_enable_shared_from_this(shared_count<T, VoidAllocator, Deleter> const &, ...)
  58. {}
  59. } // namespace ipcdetail
  60. //!shared_ptr stores a pointer to a dynamically allocated object.
  61. //!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to
  62. //!it is destroyed or reset.
  63. //!
  64. //!shared_ptr is parameterized on
  65. //!T (the type of the object pointed to), VoidAllocator (the void allocator to be used
  66. //!to allocate the auxiliary data) and Deleter (the deleter whose
  67. //!operator() will be used to delete the object.
  68. //!
  69. //!The internal pointer will be of the same pointer type as typename
  70. //!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is
  71. //!offset_ptr<void>, the internal pointer will be offset_ptr<T>).
  72. //!
  73. //!Because the implementation uses reference counting, cycles of shared_ptr
  74. //!instances will not be reclaimed. For example, if main() holds a
  75. //!shared_ptr to A, which directly or indirectly holds a shared_ptr back
  76. //!to A, A's use count will be 2. Destruction of the original shared_ptr
  77. //!will leave A dangling with a use count of 1.
  78. //!Use weak_ptr to "break cycles."
  79. template<class T, class VoidAllocator, class Deleter>
  80. class shared_ptr
  81. {
  82. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  83. private:
  84. typedef shared_ptr<T, VoidAllocator, Deleter> this_type;
  85. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  86. public:
  87. typedef T element_type;
  88. typedef T value_type;
  89. typedef typename boost::container::
  90. allocator_traits<VoidAllocator>::pointer void_ptr;
  91. typedef typename boost::intrusive::
  92. pointer_traits<void_ptr>::template
  93. rebind_pointer<T>::type pointer;
  94. typedef typename ipcdetail::add_reference
  95. <value_type>::type reference;
  96. typedef typename ipcdetail::add_reference
  97. <const value_type>::type const_reference;
  98. typedef typename boost::intrusive::
  99. pointer_traits<void_ptr>::template
  100. rebind_pointer<const Deleter>::type const_deleter_pointer;
  101. typedef typename boost::intrusive::
  102. pointer_traits<void_ptr>::template
  103. rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
  104. BOOST_COPYABLE_AND_MOVABLE(shared_ptr)
  105. public:
  106. //!Constructs an empty shared_ptr.
  107. //!Use_count() == 0 && get()== 0.
  108. shared_ptr()
  109. : m_pn() // never throws
  110. {}
  111. //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated
  112. //!with a copy of a and the object will be deleted with a copy of d.
  113. //!Requirements: Deleter and A's copy constructor must not throw.
  114. explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
  115. : m_pn(p, a, d)
  116. {
  117. //Check that the pointer passed is of the same type that
  118. //the pointer the allocator defines or it's a raw pointer
  119. typedef typename boost::intrusive::
  120. pointer_traits<pointer>::template
  121. rebind_pointer<T>::type ParameterPointer;
  122. BOOST_INTERPROCESS_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
  123. (ipcdetail::is_pointer<pointer>::value));
  124. ipcdetail::sp_enable_shared_from_this<T, VoidAllocator, Deleter>( m_pn, ipcdetail::to_raw_pointer(p), ipcdetail::to_raw_pointer(p) );
  125. }
  126. //!Copy constructs a shared_ptr. If r is empty, constructs an empty shared_ptr. Otherwise, constructs
  127. //!a shared_ptr that shares ownership with r. Never throws.
  128. shared_ptr(const shared_ptr &r)
  129. : m_pn(r.m_pn) // never throws
  130. {}
  131. //!Constructs a shared_ptr that shares ownership with other and stores p.
  132. //!Postconditions: get() == p && use_count() == r.use_count().
  133. //!Throws: nothing.
  134. shared_ptr(const shared_ptr &other, const pointer &p)
  135. : m_pn(other.m_pn, p)
  136. {}
  137. //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs
  138. //!a shared_ptr that shares ownership with r. Never throws.
  139. template<class Y>
  140. shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r)
  141. : m_pn(r.m_pn) // never throws
  142. {}
  143. //!Constructs a shared_ptr that shares ownership with r and stores
  144. //!a copy of the pointer stored in r.
  145. template<class Y>
  146. explicit shared_ptr(weak_ptr<Y, VoidAllocator, Deleter> const & r)
  147. : m_pn(r.m_pn) // may throw
  148. {}
  149. //!Move-Constructs a shared_ptr that takes ownership of other resource and
  150. //!other is put in default-constructed state.
  151. //!Throws: nothing.
  152. explicit shared_ptr(BOOST_RV_REF(shared_ptr) other)
  153. : m_pn()
  154. { this->swap(other); }
  155. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  156. template<class Y>
  157. shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::static_cast_tag)
  158. : m_pn( pointer(static_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
  159. , r.m_pn)
  160. {}
  161. template<class Y>
  162. shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::const_cast_tag)
  163. : m_pn( pointer(const_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
  164. , r.m_pn)
  165. {}
  166. template<class Y>
  167. shared_ptr(shared_ptr<Y, VoidAllocator, Deleter> const & r, ipcdetail::dynamic_cast_tag)
  168. : m_pn( pointer(dynamic_cast<T*>(ipcdetail::to_raw_pointer(r.m_pn.to_raw_pointer())))
  169. , r.m_pn)
  170. {
  171. if(!m_pn.to_raw_pointer()){ // need to allocate new counter -- the cast failed
  172. m_pn = ipcdetail::shared_count<T, VoidAllocator, Deleter>();
  173. }
  174. }
  175. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  176. //!Equivalent to shared_ptr(r).swap(*this).
  177. //!Never throws
  178. template<class Y>
  179. shared_ptr & operator=(shared_ptr<Y, VoidAllocator, Deleter> const & r)
  180. {
  181. m_pn = r.m_pn; // shared_count::op= doesn't throw
  182. return *this;
  183. }
  184. //!Equivalent to shared_ptr(r).swap(*this).
  185. //!Never throws
  186. shared_ptr & operator=(BOOST_COPY_ASSIGN_REF(shared_ptr) r)
  187. {
  188. m_pn = r.m_pn; // shared_count::op= doesn't throw
  189. return *this;
  190. }
  191. //!Move-assignment. Equivalent to shared_ptr(other).swap(*this).
  192. //!Never throws
  193. shared_ptr & operator=(BOOST_RV_REF(shared_ptr) other) // never throws
  194. {
  195. this_type(other).swap(*this);
  196. return *this;
  197. }
  198. //!This is equivalent to:
  199. //!this_type().swap(*this);
  200. void reset()
  201. {
  202. this_type().swap(*this);
  203. }
  204. //!This is equivalent to:
  205. //!this_type(p, a, d).swap(*this);
  206. template<class Pointer>
  207. void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter())
  208. {
  209. //Check that the pointer passed is of the same type that
  210. //the pointer the allocator defines or it's a raw pointer
  211. typedef typename boost::intrusive::
  212. pointer_traits<Pointer>::template
  213. rebind_pointer<T>::type ParameterPointer;
  214. BOOST_INTERPROCESS_STATIC_ASSERT((ipcdetail::is_same<pointer, ParameterPointer>::value) ||
  215. (ipcdetail::is_pointer<Pointer>::value));
  216. this_type(p, a, d).swap(*this);
  217. }
  218. template<class Y>
  219. void reset(shared_ptr<Y, VoidAllocator, Deleter> const & r, const pointer &p)
  220. {
  221. this_type(r, p).swap(*this);
  222. }
  223. //!Returns a reference to the
  224. //!pointed type
  225. reference operator* () const // never throws
  226. { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return *m_pn.to_raw_pointer(); }
  227. //!Returns the pointer pointing
  228. //!to the owned object
  229. pointer operator-> () const // never throws
  230. { BOOST_ASSERT(m_pn.to_raw_pointer() != 0); return m_pn.to_raw_pointer(); }
  231. //!Returns the pointer pointing
  232. //!to the owned object
  233. pointer get() const // never throws
  234. { return m_pn.to_raw_pointer(); }
  235. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  236. // implicit conversion to "bool"
  237. void unspecified_bool_type_func() const {}
  238. typedef void (this_type::*unspecified_bool_type)() const;
  239. operator unspecified_bool_type() const // never throws
  240. { return !m_pn.to_raw_pointer() ? 0 : &this_type::unspecified_bool_type_func; }
  241. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  242. //!Not operator.
  243. //!Returns true if this->get() != 0, false otherwise
  244. bool operator! () const // never throws
  245. { return !m_pn.to_raw_pointer(); }
  246. //!Returns use_count() == 1.
  247. //!unique() might be faster than use_count()
  248. bool unique() const // never throws
  249. { return m_pn.unique(); }
  250. //!Returns the number of shared_ptr objects, *this included,
  251. //!that share ownership with *this, or an unspecified nonnegative
  252. //!value when *this is empty.
  253. //!use_count() is not necessarily efficient. Use only for
  254. //!debugging and testing purposes, not for production code.
  255. long use_count() const // never throws
  256. { return m_pn.use_count(); }
  257. //!Exchanges the contents of the two
  258. //!smart pointers.
  259. void swap(shared_ptr<T, VoidAllocator, Deleter> & other) // never throws
  260. { m_pn.swap(other.m_pn); }
  261. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  262. template<class T2, class A2, class Deleter2>
  263. bool _internal_less(shared_ptr<T2, A2, Deleter2> const & rhs) const
  264. { return m_pn < rhs.m_pn; }
  265. const_deleter_pointer get_deleter() const
  266. { return m_pn.get_deleter(); }
  267. // const_allocator_pointer get_allocator() const
  268. // { return m_pn.get_allocator(); }
  269. private:
  270. template<class T2, class A2, class Deleter2> friend class shared_ptr;
  271. template<class T2, class A2, class Deleter2> friend class weak_ptr;
  272. ipcdetail::shared_count<T, VoidAllocator, Deleter> m_pn; // reference counter
  273. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  274. }; // shared_ptr
  275. template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
  276. bool operator==(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
  277. { return a.get() == b.get(); }
  278. template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
  279. bool operator!=(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
  280. { return a.get() != b.get(); }
  281. template<class T, class VoidAllocator, class Deleter, class U, class VoidAllocator2, class Deleter2> inline
  282. bool operator<(shared_ptr<T, VoidAllocator, Deleter> const & a, shared_ptr<U, VoidAllocator2, Deleter2> const & b)
  283. { return a._internal_less(b); }
  284. template<class T, class VoidAllocator, class Deleter> inline
  285. void swap(shared_ptr<T, VoidAllocator, Deleter> & a, shared_ptr<T, VoidAllocator, Deleter> & b)
  286. { a.swap(b); }
  287. template<class T, class VoidAllocator, class Deleter, class U> inline
  288. shared_ptr<T, VoidAllocator, Deleter> static_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
  289. { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::static_cast_tag()); }
  290. template<class T, class VoidAllocator, class Deleter, class U> inline
  291. shared_ptr<T, VoidAllocator, Deleter> const_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
  292. { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::const_cast_tag()); }
  293. template<class T, class VoidAllocator, class Deleter, class U> inline
  294. shared_ptr<T, VoidAllocator, Deleter> dynamic_pointer_cast(shared_ptr<U, VoidAllocator, Deleter> const & r)
  295. { return shared_ptr<T, VoidAllocator, Deleter>(r, ipcdetail::dynamic_cast_tag()); }
  296. // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
  297. template<class T, class VoidAllocator, class Deleter> inline
  298. T * to_raw_pointer(shared_ptr<T, VoidAllocator, Deleter> const & p)
  299. { return p.get(); }
  300. // operator<<
  301. template<class E, class T, class Y, class VoidAllocator, class Deleter> inline
  302. std::basic_ostream<E, T> & operator<<
  303. (std::basic_ostream<E, T> & os, shared_ptr<Y, VoidAllocator, Deleter> const & p)
  304. { os << p.get(); return os; }
  305. //!Returns the type of a shared pointer
  306. //!of type T with the allocator boost::interprocess::allocator allocator
  307. //!and boost::interprocess::deleter deleter
  308. //!that can be constructed in the given managed segment type.
  309. template<class T, class ManagedMemory>
  310. struct managed_shared_ptr
  311. {
  312. typedef typename ManagedMemory::template allocator<void>::type void_allocator;
  313. typedef typename ManagedMemory::template deleter<T>::type deleter;
  314. typedef shared_ptr< T, void_allocator, deleter> type;
  315. };
  316. //!Returns an instance of a shared pointer constructed
  317. //!with the default allocator and deleter from a pointer
  318. //!of type T that has been allocated in the passed managed segment
  319. template<class T, class ManagedMemory>
  320. inline typename managed_shared_ptr<T, ManagedMemory>::type
  321. make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory)
  322. {
  323. return typename managed_shared_ptr<T, ManagedMemory>::type
  324. ( constructed_object
  325. , managed_memory.template get_allocator<void>()
  326. , managed_memory.template get_deleter<T>()
  327. );
  328. }
  329. //!Returns an instance of a shared pointer constructed
  330. //!with the default allocator and deleter from a pointer
  331. //!of type T that has been allocated in the passed managed segment.
  332. //!Does not throw, return null shared pointer in error.
  333. template<class T, class ManagedMemory>
  334. inline typename managed_shared_ptr<T, ManagedMemory>::type
  335. make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory, const std::nothrow_t &)
  336. {
  337. BOOST_INTERPROCESS_TRY{
  338. return typename managed_shared_ptr<T, ManagedMemory>::type
  339. ( constructed_object
  340. , managed_memory.template get_allocator<void>()
  341. , managed_memory.template get_deleter<T>()
  342. );
  343. }
  344. BOOST_INTERPROCESS_CATCH(...){
  345. return typename managed_shared_ptr<T, ManagedMemory>::type();
  346. } BOOST_INTERPROCESS_CATCH_END
  347. }
  348. } // namespace interprocess
  349. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  350. #if defined(_MSC_VER) && (_MSC_VER < 1400)
  351. // to_raw_pointer() enables boost::mem_fn to recognize shared_ptr
  352. template<class T, class VoidAllocator, class Deleter> inline
  353. T * to_raw_pointer(boost::interprocess::shared_ptr<T, VoidAllocator, Deleter> const & p)
  354. { return p.get(); }
  355. #endif
  356. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  357. } // namespace boost
  358. #include <boost/interprocess/detail/config_end.hpp>
  359. #endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED