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