shared_count.hpp 11 KB

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