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