File indexing completed on 2025-01-18 09:51:42
0001 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_STD_ATOMIC_HPP_INCLUDED
0003
0004
0005
0006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
0007 # pragma once
0008 #endif
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
0019 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
0020 #include <boost/config.hpp>
0021 #include <atomic>
0022 #include <cstdint>
0023
0024 #if defined(BOOST_SP_REPORT_IMPLEMENTATION)
0025
0026 #include <boost/config/pragma_message.hpp>
0027 BOOST_PRAGMA_MESSAGE("Using std::atomic sp_counted_base")
0028
0029 #endif
0030
0031 namespace boost
0032 {
0033
0034 namespace detail
0035 {
0036
0037 inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0038 {
0039 pw->fetch_add( 1, std::memory_order_relaxed );
0040 }
0041
0042 inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0043 {
0044 return pw->fetch_sub( 1, std::memory_order_acq_rel );
0045 }
0046
0047 inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
0048 {
0049
0050
0051
0052
0053 std::int_least32_t r = pw->load( std::memory_order_relaxed );
0054
0055 for( ;; )
0056 {
0057 if( r == 0 )
0058 {
0059 return r;
0060 }
0061
0062 if( pw->compare_exchange_weak( r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed ) )
0063 {
0064 return r;
0065 }
0066 }
0067 }
0068
0069 class BOOST_SYMBOL_VISIBLE sp_counted_base
0070 {
0071 private:
0072
0073 sp_counted_base( sp_counted_base const & );
0074 sp_counted_base & operator= ( sp_counted_base const & );
0075
0076 std::atomic_int_least32_t use_count_;
0077 std::atomic_int_least32_t weak_count_;
0078
0079 public:
0080
0081 sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
0082 {
0083 }
0084
0085 virtual ~sp_counted_base()
0086 {
0087 }
0088
0089
0090
0091
0092 virtual void dispose() BOOST_SP_NOEXCEPT = 0;
0093
0094
0095
0096 virtual void destroy() BOOST_SP_NOEXCEPT
0097 {
0098 delete this;
0099 }
0100
0101 virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
0102 virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
0103 virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
0104
0105 void add_ref_copy() BOOST_SP_NOEXCEPT
0106 {
0107 atomic_increment( &use_count_ );
0108 }
0109
0110 bool add_ref_lock() BOOST_SP_NOEXCEPT
0111 {
0112 return atomic_conditional_increment( &use_count_ ) != 0;
0113 }
0114
0115 void release() BOOST_SP_NOEXCEPT
0116 {
0117 if( atomic_decrement( &use_count_ ) == 1 )
0118 {
0119 dispose();
0120 weak_release();
0121 }
0122 }
0123
0124 void weak_add_ref() BOOST_SP_NOEXCEPT
0125 {
0126 atomic_increment( &weak_count_ );
0127 }
0128
0129 void weak_release() BOOST_SP_NOEXCEPT
0130 {
0131 if( atomic_decrement( &weak_count_ ) == 1 )
0132 {
0133 destroy();
0134 }
0135 }
0136
0137 long use_count() const BOOST_SP_NOEXCEPT
0138 {
0139 return use_count_.load( std::memory_order_acquire );
0140 }
0141 };
0142
0143 }
0144
0145 }
0146
0147 #endif