shared_count.hpp 11 KB

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