shared_count.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp
  4. //
  5. // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003
  6. // (C) Copyright Peter Dimov 2004-2005
  7. // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
  8. // Software License, Version 1.0. (See accompanying file
  9. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // See http://www.boost.org/libs/interprocess for documentation.
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
  15. #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
  16. #ifndef BOOST_CONFIG_HPP
  17. # include <boost/config.hpp>
  18. #endif
  19. #
  20. #if defined(BOOST_HAS_PRAGMA_ONCE)
  21. # pragma once
  22. #endif
  23. #include <boost/interprocess/detail/config_begin.hpp>
  24. #include <boost/interprocess/detail/workaround.hpp>
  25. #include <boost/checked_delete.hpp>
  26. #include <boost/intrusive/pointer_traits.hpp>
  27. #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
  28. #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
  29. #include <boost/interprocess/detail/utilities.hpp>
  30. #include <boost/container/allocator_traits.hpp>
  31. #include <boost/core/no_exceptions_support.hpp>
  32. #include <boost/move/adl_move_swap.hpp>
  33. #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less
  34. #include <boost/container/detail/placement_new.hpp>
  35. namespace boost {
  36. namespace interprocess {
  37. namespace ipcdetail{
  38. template<class T, class VoidAllocator, class Deleter>
  39. class weak_count;
  40. template<class T, class VoidAllocator, class Deleter>
  41. class shared_count
  42. {
  43. public:
  44. typedef typename boost::intrusive::
  45. pointer_traits<typename VoidAllocator::pointer>::template
  46. rebind_pointer<T>::type pointer;
  47. private:
  48. typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
  49. typedef typename boost::intrusive::
  50. pointer_traits<typename VoidAllocator::pointer>::template
  51. rebind_pointer<counted_impl>::type counted_impl_ptr;
  52. typedef typename boost::intrusive::
  53. pointer_traits<typename VoidAllocator::pointer>::template
  54. rebind_pointer<sp_counted_base>::type counted_base_ptr;
  55. typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits;
  56. typedef typename vallocator_traits::template
  57. portable_rebind_alloc<counted_impl>::type counted_impl_allocator;
  58. typedef typename boost::intrusive::
  59. pointer_traits<typename VoidAllocator::pointer>::template
  60. rebind_pointer<const Deleter>::type const_deleter_pointer;
  61. typedef typename boost::intrusive::
  62. pointer_traits<typename VoidAllocator::pointer>::template
  63. rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
  64. pointer m_px;
  65. counted_impl_ptr m_pi;
  66. template <class T2, class VoidAllocator2, class Deleter2>
  67. friend class weak_count;
  68. template <class T2, class VoidAllocator2, class Deleter2>
  69. friend class shared_count;
  70. public:
  71. shared_count()
  72. : m_px(0), m_pi(0) // nothrow
  73. {}
  74. template <class Ptr>
  75. shared_count(const shared_count &other_shared_count, const Ptr &p)
  76. : m_px(p), m_pi(other_shared_count.m_pi)
  77. {}
  78. template <class Ptr>
  79. shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
  80. : m_px(p), m_pi(0)
  81. {
  82. BOOST_TRY{
  83. if(p){
  84. counted_impl_allocator alloc(a);
  85. m_pi = alloc.allocate(1);
  86. //Anti-exception deallocator
  87. scoped_ptr<counted_impl,
  88. scoped_ptr_dealloc_functor<counted_impl_allocator> >
  89. deallocator(m_pi, alloc);
  90. //It's more correct to use VoidAllocator::construct but
  91. //this needs copy constructor and we don't like it
  92. ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d);
  93. deallocator.release();
  94. }
  95. }
  96. BOOST_CATCH (...){
  97. d(p); // delete p
  98. BOOST_RETHROW
  99. }
  100. BOOST_CATCH_END
  101. }
  102. ~shared_count() // nothrow
  103. {
  104. if(m_pi)
  105. m_pi->release();
  106. }
  107. shared_count(shared_count const & r)
  108. : m_px(r.m_px), m_pi(r.m_pi) // nothrow
  109. { if( m_pi != 0 ) m_pi->add_ref_copy(); }
  110. //this is a test
  111. template<class Y>
  112. explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
  113. : m_px(r.m_px), m_pi(r.m_pi) // nothrow
  114. { if( m_pi != 0 ) m_pi->add_ref_copy(); }
  115. //this is a test
  116. template<class Y>
  117. explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
  118. : m_px(ptr), m_pi(r.m_pi) // nothrow
  119. { if( m_pi != 0 ) m_pi->add_ref_copy(); }
  120. /*
  121. explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
  122. // throws bad_weak_ptr when r.use_count() == 0
  123. : m_pi( r.m_pi )
  124. {
  125. if( m_pi == 0 || !m_pi->add_ref_lock() ){
  126. boost::throw_exception( boost::interprocess::bad_weak_ptr() );
  127. }
  128. }
  129. */
  130. template<class Y>
  131. explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
  132. // throws bad_weak_ptr when r.use_count() == 0
  133. : m_px(r.m_px), m_pi( r.m_pi )
  134. {
  135. if( m_pi == 0 || !m_pi->add_ref_lock() ){
  136. throw( boost::interprocess::bad_weak_ptr() );
  137. }
  138. }
  139. const pointer &to_raw_pointer() const
  140. { return m_px; }
  141. pointer &to_raw_pointer()
  142. { return m_px; }
  143. shared_count & operator= (shared_count const & r) // nothrow
  144. {
  145. m_px = r.m_px;
  146. counted_impl_ptr tmp = r.m_pi;
  147. if( tmp != m_pi ){
  148. if(tmp != 0) tmp->add_ref_copy();
  149. if(m_pi != 0) m_pi->release();
  150. m_pi = tmp;
  151. }
  152. return *this;
  153. }
  154. template<class Y>
  155. shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
  156. {
  157. m_px = r.m_px;
  158. counted_impl_ptr tmp = r.m_pi;
  159. if( tmp != m_pi ){
  160. if(tmp != 0) tmp->add_ref_copy();
  161. if(m_pi != 0) m_pi->release();
  162. m_pi = tmp;
  163. }
  164. return *this;
  165. }
  166. void swap(shared_count & r) // nothrow
  167. { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
  168. long use_count() const // nothrow
  169. { return m_pi != 0? m_pi->use_count(): 0; }
  170. bool unique() const // nothrow
  171. { return use_count() == 1; }
  172. const_deleter_pointer get_deleter() const
  173. { return m_pi ? m_pi->get_deleter() : 0; }
  174. // const_allocator_pointer get_allocator() const
  175. // { return m_pi ? m_pi->get_allocator() : 0; }
  176. template<class T2, class VoidAllocator2, class Deleter2>
  177. bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
  178. { return this->m_pi == other.m_pi; }
  179. template<class T2, class VoidAllocator2, class Deleter2>
  180. bool internal_less (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
  181. { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
  182. };
  183. template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  184. bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
  185. { return a.internal_equal(b); }
  186. template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  187. bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
  188. { return a.internal_less(b); }
  189. template<class T, class VoidAllocator, class Deleter>
  190. class weak_count
  191. {
  192. public:
  193. typedef typename boost::intrusive::
  194. pointer_traits<typename VoidAllocator::pointer>::template
  195. rebind_pointer<T>::type pointer;
  196. private:
  197. typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
  198. typedef typename boost::intrusive::
  199. pointer_traits<typename VoidAllocator::pointer>::template
  200. rebind_pointer<counted_impl>::type counted_impl_ptr;
  201. typedef typename boost::intrusive::
  202. pointer_traits<typename VoidAllocator::pointer>::template
  203. rebind_pointer<sp_counted_base>::type counted_base_ptr;
  204. pointer m_px;
  205. counted_impl_ptr m_pi;
  206. template <class T2, class VoidAllocator2, class Deleter2>
  207. friend class weak_count;
  208. template <class T2, class VoidAllocator2, class Deleter2>
  209. friend class shared_count;
  210. public:
  211. weak_count(): m_px(0), m_pi(0) // nothrow
  212. {}
  213. template <class Y>
  214. explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
  215. : m_px(r.m_px), m_pi(r.m_pi) // nothrow
  216. { if(m_pi != 0) m_pi->weak_add_ref(); }
  217. weak_count(weak_count const & r)
  218. : m_px(r.m_px), m_pi(r.m_pi) // nothrow
  219. { if(m_pi != 0) m_pi->weak_add_ref(); }
  220. template<class Y>
  221. weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
  222. : m_px(r.m_px), m_pi(r.m_pi) // nothrow
  223. { if(m_pi != 0) m_pi->weak_add_ref(); }
  224. ~weak_count() // nothrow
  225. { if(m_pi != 0) m_pi->weak_release(); }
  226. template<class Y>
  227. weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
  228. {
  229. m_px = r.m_px;
  230. counted_impl_ptr tmp = r.m_pi;
  231. if(tmp != 0) tmp->weak_add_ref();
  232. if(m_pi != 0) m_pi->weak_release();
  233. m_pi = tmp;
  234. return *this;
  235. }
  236. weak_count & operator= (weak_count const & r) // nothrow
  237. {
  238. m_px = r.m_px;
  239. counted_impl_ptr tmp = r.m_pi;
  240. if(tmp != 0) tmp->weak_add_ref();
  241. if(m_pi != 0) m_pi->weak_release();
  242. m_pi = tmp;
  243. return *this;
  244. }
  245. void set_pointer(const pointer &ptr)
  246. { m_px = ptr; }
  247. template<class Y>
  248. weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow
  249. {
  250. counted_impl_ptr tmp = r.m_pi;
  251. if(tmp != 0) tmp->weak_add_ref();
  252. if(m_pi != 0) m_pi->weak_release();
  253. m_pi = tmp;
  254. return *this;
  255. }
  256. void swap(weak_count & r) // nothrow
  257. { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
  258. long use_count() const // nothrow
  259. { return m_pi != 0? m_pi->use_count() : 0; }
  260. template<class T2, class VoidAllocator2, class Deleter2>
  261. bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
  262. { return this->m_pi == other.m_pi; }
  263. template<class T2, class VoidAllocator2, class Deleter2>
  264. bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
  265. { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
  266. };
  267. template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  268. bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
  269. { return a.internal_equal(b); }
  270. template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  271. bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
  272. { return a.internal_less(b); }
  273. } // namespace ipcdetail
  274. } // namespace interprocess
  275. } // namespace boost
  276. #include <boost/interprocess/detail/config_end.hpp>
  277. #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED