Line data Source code
1 : #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED 2 : #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED 3 : 4 : // MS compatible compilers support #pragma once 5 : 6 : #if defined(_MSC_VER) && (_MSC_VER >= 1020) 7 : # pragma once 8 : #endif 9 : 10 : // detail/sp_counted_base_std_atomic.hpp - C++11 std::atomic 11 : // 12 : // Copyright (c) 2007, 2013 Peter Dimov 13 : // 14 : // Distributed under the Boost Software License, Version 1.0. 15 : // See accompanying file LICENSE_1_0.txt or copy at 16 : // http://www.boost.org/LICENSE_1_0.txt 17 : 18 : #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> 19 : #include <boost/smart_ptr/detail/sp_noexcept.hpp> 20 : #include <boost/config.hpp> 21 : #include <atomic> 22 : #include <cstdint> 23 : 24 : namespace boost 25 : { 26 : 27 : namespace detail 28 : { 29 : 30 0 : inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT 31 : { 32 0 : pw->fetch_add( 1, std::memory_order_relaxed ); 33 : } 34 : 35 0 : inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT 36 : { 37 0 : return pw->fetch_sub( 1, std::memory_order_acq_rel ); 38 : } 39 : 40 0 : inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT 41 : { 42 : // long r = *pw; 43 : // if( r != 0 ) ++*pw; 44 : // return r; 45 : 46 0 : std::int_least32_t r = pw->load( std::memory_order_relaxed ); 47 : 48 0 : for( ;; ) 49 : { 50 0 : if( r == 0 ) 51 : { 52 : return r; 53 : } 54 : 55 0 : if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) ) 56 : { 57 : return r; 58 : } 59 : } 60 : } 61 : 62 : class BOOST_SYMBOL_VISIBLE sp_counted_base 63 : { 64 : private: 65 : 66 : sp_counted_base( sp_counted_base const & ); 67 : sp_counted_base & operator= ( sp_counted_base const & ); 68 : 69 : std::atomic_int_least32_t use_count_; // #shared 70 : std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0) 71 : 72 : public: 73 : 74 0 : sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 ) 75 : { 76 : } 77 : 78 : virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/ 79 : { 80 : } 81 : 82 : // dispose() is called when use_count_ drops to zero, to release 83 : // the resources managed by *this. 84 : 85 : virtual void dispose() BOOST_SP_NOEXCEPT = 0; 86 : 87 : // destroy() is called when weak_count_ drops to zero. 88 : 89 0 : virtual void destroy() BOOST_SP_NOEXCEPT 90 : { 91 0 : delete this; 92 0 : } 93 : 94 : virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0; 95 : virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0; 96 : virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0; 97 : 98 0 : void add_ref_copy() BOOST_SP_NOEXCEPT 99 : { 100 0 : atomic_increment( &use_count_ ); 101 0 : } 102 : 103 0 : bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success 104 : { 105 0 : return atomic_conditional_increment( &use_count_ ) != 0; 106 : } 107 : 108 0 : void release() BOOST_SP_NOEXCEPT 109 : { 110 0 : if( atomic_decrement( &use_count_ ) == 1 ) 111 : { 112 0 : dispose(); 113 0 : weak_release(); 114 : } 115 0 : } 116 : 117 : void weak_add_ref() BOOST_SP_NOEXCEPT 118 : { 119 : atomic_increment( &weak_count_ ); 120 : } 121 : 122 0 : void weak_release() BOOST_SP_NOEXCEPT 123 : { 124 0 : if( atomic_decrement( &weak_count_ ) == 1 ) 125 : { 126 0 : destroy(); 127 : } 128 0 : } 129 : 130 0 : long use_count() const BOOST_SP_NOEXCEPT 131 : { 132 0 : return use_count_.load( std::memory_order_acquire ); 133 : } 134 : }; 135 : 136 : } // namespace detail 137 : 138 : } // namespace boost 139 : 140 : #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED