diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc index 5b452c7..d3210d7 100644 --- a/doc/smart_ptr.adoc +++ b/doc/smart_ptr.adoc @@ -41,6 +41,8 @@ include::smart_ptr/pointer_cast.adoc[] include::smart_ptr/pointer_to_other.adoc[] +include::smart_ptr/atomic_shared_ptr.adoc[] + // appendix include::smart_ptr/techniques.adoc[] diff --git a/doc/smart_ptr/atomic_shared_ptr.adoc b/doc/smart_ptr/atomic_shared_ptr.adoc new file mode 100644 index 0000000..3c8d27e --- /dev/null +++ b/doc/smart_ptr/atomic_shared_ptr.adoc @@ -0,0 +1,154 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#atomic_shared_ptr] +# atomic_shared_ptr +:toc: +:toc-title: +:idprefix: atomic_shared_ptr_ + +## Description + +The class template `atomic_shared_ptr` implements the interface of `std::atomic` +for a contained value of type `shared_ptr`. + +## Synopsis + +`atomic_shared_ptr` is defined in ``. + +``` +namespace boost { + + template class atomic_shared_ptr { + private: + + shared_ptr p_; // exposition only + + atomic_shared_ptr(const atomic_shared_ptr&) = delete; + atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete; + + public: + + atomic_shared_ptr() noexcept = default; + constexpr atomic_shared_ptr( shared_ptr p ) noexcept; + + atomic_shared_ptr& operator=( shared_ptr r ) noexcept; + + bool is_lock_free() const noexcept; + + shared_ptr load( int = 0 ) const noexcept; + operator shared_ptr() const noexcept; + + void store( shared_ptr r, int = 0 ) noexcept; + + shared_ptr exchange( shared_ptr r, int = 0 ) noexcept; + + bool compare_exchange_weak( shared_ptr& v, const shared_ptr& w, int, int ) noexcept; + bool compare_exchange_weak( shared_ptr& v, const shared_ptr& w, int = 0 ) noexcept; + bool compare_exchange_strong( shared_ptr& v, const shared_ptr& w, int, int ) noexcept; + bool compare_exchange_strong( shared_ptr& v, const shared_ptr& w, int = 0 ) noexcept; + + bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int, int ) noexcept; + bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int = 0 ) noexcept; + bool compare_exchange_strong( shared_ptr& v, shared_ptr&& w, int, int ) noexcept; + bool compare_exchange_strong( shared_ptr& v, shared_ptr&& w, int = 0 ) noexcept; + }; +} +``` + +## Members + +``` +constexpr atomic_shared_ptr( shared_ptr p ) noexcept; +``` +[none] +* {blank} ++ +Effects:: Initializes `p_` to `p`. + +``` +atomic_shared_ptr& operator=( shared_ptr r ) noexcept; +``` +[none] +* {blank} ++ +Effects:: `atomic_store( &p_, r )`. +Returns:: `*this`. + +``` +bool is_lock_free() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `false`. + +``` +shared_ptr load( int = 0 ) const noexcept; +``` +``` +operator shared_ptr() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `atomic_load( &p_ )`. + +NOTE: The `int` argument is intended to be of type `memory_order`, but is ignored in this implementation. + +``` +void store( shared_ptr r, int = 0 ) noexcept; +``` +[none] +* {blank} ++ +Effects:: `atomic_store( &p_, r )`. + +``` +shared_ptr exchange( shared_ptr r, int = 0 ) noexcept; +``` +[none] +* {blank} ++ +Returns:: `atomic_exchange( &p_, r )`. + +``` +bool compare_exchange_weak( shared_ptr& v, const shared_ptr& w, int, int ) noexcept; +``` +``` +bool compare_exchange_weak( shared_ptr& v, const shared_ptr& w, int = 0 ) noexcept; +``` +``` +bool compare_exchange_strong( shared_ptr& v, const shared_ptr& w, int, int ) noexcept; +``` +``` +bool compare_exchange_strong( shared_ptr& v, const shared_ptr& w, int = 0 ) noexcept; +``` +[none] +* {blank} ++ +Returns:: `atomic_compare_exchange( &p_, &v, w )`. + +``` +bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int, int ) noexcept; +``` +``` +bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int = 0 ) noexcept; +``` +``` +bool compare_exchange_strong( shared_ptr& v, shared_ptr&& w, int, int ) noexcept; +``` +``` +bool compare_exchange_strong( shared_ptr& v, shared_ptr&& w, int = 0 ) noexcept; +``` +[none] +* {blank} ++ +Returns:: `atomic_compare_exchange( &p_, &v, std::move( w ) )`. + diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc index ecbef1d..2154014 100644 --- a/doc/smart_ptr/introduction.adoc +++ b/doc/smart_ptr/introduction.adoc @@ -42,6 +42,7 @@ In addition, the library contains the following supporting utility functions and * `<>`, a helper trait for converting one smart pointer type to another; * `<>` and companions, generic smart pointer casts; * `<>`, a helper base class containing a reference count. +* `<>`, a helper class implementing the interface of `std::atomic` for a value of type `shared_ptr`. As a general rule, the destructor or `operator delete` for an object managed by pointers in the library are not allowed to throw exceptions. diff --git a/include/boost/smart_ptr/atomic_shared_ptr.hpp b/include/boost/smart_ptr/atomic_shared_ptr.hpp index 60136e5..fdc97bd 100644 --- a/include/boost/smart_ptr/atomic_shared_ptr.hpp +++ b/include/boost/smart_ptr/atomic_shared_ptr.hpp @@ -33,7 +33,12 @@ public: { } - BOOST_CONSTEXPR atomic_shared_ptr( shared_ptr p ) BOOST_SP_NOEXCEPT: p_( p ) + BOOST_CONSTEXPR atomic_shared_ptr( shared_ptr p ) BOOST_SP_NOEXCEPT +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + : p_( std::move( p ) ) +#else + : p_( p ) +#endif { } @@ -114,7 +119,7 @@ public: #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int, int ) BOOST_SP_NOEXCEPT + bool compare_exchange_weak( shared_ptr& v, shared_ptr&& w, int, int ) BOOST_SP_NOEXCEPT { return atomic_compare_exchange( &p_, &v, std::move( w ) ); }