atomic_shared_ptr.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
  3. //
  4. // atomic_shared_ptr.hpp
  5. //
  6. // Copyright 2017 Peter Dimov
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See
  9. // 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/smart_ptr/ for documentation.
  13. //
  14. #include <boost/smart_ptr/detail/requires_cxx11.hpp>
  15. #include <boost/smart_ptr/shared_ptr.hpp>
  16. #include <boost/smart_ptr/detail/spinlock.hpp>
  17. #include <cstring>
  18. namespace boost
  19. {
  20. template<class T> class atomic_shared_ptr
  21. {
  22. private:
  23. boost::shared_ptr<T> p_;
  24. mutable boost::detail::spinlock l_;
  25. atomic_shared_ptr(const atomic_shared_ptr&);
  26. atomic_shared_ptr& operator=(const atomic_shared_ptr&);
  27. private:
  28. bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
  29. {
  30. l_.lock();
  31. if( p_._internal_equiv( v ) )
  32. {
  33. p_.swap( w );
  34. l_.unlock();
  35. return true;
  36. }
  37. else
  38. {
  39. shared_ptr<T> tmp( p_ );
  40. l_.unlock();
  41. tmp.swap( v );
  42. return false;
  43. }
  44. }
  45. public:
  46. #if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )
  47. constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
  48. {
  49. }
  50. atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
  51. : p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
  52. {
  53. }
  54. #else
  55. atomic_shared_ptr() BOOST_SP_NOEXCEPT
  56. {
  57. boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
  58. std::memcpy( &l_, &init, sizeof( init ) );
  59. }
  60. atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
  61. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  62. : p_( std::move( p ) )
  63. #else
  64. : p_( p )
  65. #endif
  66. {
  67. boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
  68. std::memcpy( &l_, &init, sizeof( init ) );
  69. }
  70. #endif
  71. atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
  72. {
  73. boost::detail::spinlock::scoped_lock lock( l_ );
  74. p_.swap( r );
  75. return *this;
  76. }
  77. BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
  78. {
  79. return false;
  80. }
  81. shared_ptr<T> load() const BOOST_SP_NOEXCEPT
  82. {
  83. boost::detail::spinlock::scoped_lock lock( l_ );
  84. return p_;
  85. }
  86. template<class M> shared_ptr<T> load( M ) const BOOST_SP_NOEXCEPT
  87. {
  88. boost::detail::spinlock::scoped_lock lock( l_ );
  89. return p_;
  90. }
  91. operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
  92. {
  93. boost::detail::spinlock::scoped_lock lock( l_ );
  94. return p_;
  95. }
  96. void store( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
  97. {
  98. boost::detail::spinlock::scoped_lock lock( l_ );
  99. p_.swap( r );
  100. }
  101. template<class M> void store( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
  102. {
  103. boost::detail::spinlock::scoped_lock lock( l_ );
  104. p_.swap( r );
  105. }
  106. shared_ptr<T> exchange( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
  107. {
  108. {
  109. boost::detail::spinlock::scoped_lock lock( l_ );
  110. p_.swap( r );
  111. }
  112. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  113. return std::move( r );
  114. #else
  115. return r;
  116. #endif
  117. }
  118. template<class M> shared_ptr<T> exchange( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
  119. {
  120. {
  121. boost::detail::spinlock::scoped_lock lock( l_ );
  122. p_.swap( r );
  123. }
  124. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  125. return std::move( r );
  126. #else
  127. return r;
  128. #endif
  129. }
  130. template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
  131. {
  132. return compare_exchange( v, w );
  133. }
  134. template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
  135. {
  136. return compare_exchange( v, w );
  137. }
  138. bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
  139. {
  140. return compare_exchange( v, w );
  141. }
  142. template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
  143. {
  144. return compare_exchange( v, w );
  145. }
  146. template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
  147. {
  148. return compare_exchange( v, w );
  149. }
  150. bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
  151. {
  152. return compare_exchange( v, w );
  153. }
  154. #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
  155. template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
  156. {
  157. return compare_exchange( v, std::move( w ) );
  158. }
  159. template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
  160. {
  161. return compare_exchange( v, std::move( w ) );
  162. }
  163. bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
  164. {
  165. return compare_exchange( v, std::move( w ) );
  166. }
  167. template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
  168. {
  169. return compare_exchange( v, std::move( w ) );
  170. }
  171. template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
  172. {
  173. return compare_exchange( v, std::move( w ) );
  174. }
  175. bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
  176. {
  177. return compare_exchange( v, std::move( w ) );
  178. }
  179. #endif
  180. };
  181. } // namespace boost
  182. #endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED