/Src/Dependencies/Boost/boost/interprocess/smart_ptr/shared_ptr.hpp

http://hadesmem.googlecode.com/ · C++ Header · 388 lines · 218 code · 66 blank · 104 comment · 8 complexity · bf2967c33c08450ad6d2ce8b1de43bca MD5 · raw file

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