File indexing completed on 2025-01-18 09:51:42
0001 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_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
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
0028 #include <boost/smart_ptr/detail/sp_obsolete.hpp>
0029 #include <boost/config.hpp>
0030
0031 #if defined(BOOST_SP_REPORT_IMPLEMENTATION)
0032
0033 #include <boost/config/pragma_message.hpp>
0034 BOOST_PRAGMA_MESSAGE("Using g++/x86 sp_counted_base")
0035
0036 #endif
0037
0038 BOOST_SP_OBSOLETE()
0039
0040 namespace boost
0041 {
0042
0043 namespace detail
0044 {
0045
0046 inline int atomic_exchange_and_add( int * pw, int dv )
0047 {
0048
0049
0050
0051
0052 int r;
0053
0054 __asm__ __volatile__
0055 (
0056 "lock\n\t"
0057 "xadd %1, %0":
0058 "=m"( *pw ), "=r"( r ):
0059 "m"( *pw ), "1"( dv ):
0060 "memory", "cc"
0061 );
0062
0063 return r;
0064 }
0065
0066 inline void atomic_increment( int * pw )
0067 {
0068
0069
0070 __asm__
0071 (
0072 "lock\n\t"
0073 "incl %0":
0074 "=m"( *pw ):
0075 "m"( *pw ):
0076 "cc"
0077 );
0078 }
0079
0080 inline int atomic_conditional_increment( int * pw )
0081 {
0082
0083
0084
0085
0086 int rv, tmp;
0087
0088 __asm__
0089 (
0090 "movl %0, %%eax\n\t"
0091 "0:\n\t"
0092 "test %%eax, %%eax\n\t"
0093 "je 1f\n\t"
0094 "movl %%eax, %2\n\t"
0095 "incl %2\n\t"
0096 "lock\n\t"
0097 "cmpxchgl %2, %0\n\t"
0098 "jne 0b\n\t"
0099 "1:":
0100 "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ):
0101 "m"( *pw ):
0102 "cc"
0103 );
0104
0105 return rv;
0106 }
0107
0108 class BOOST_SYMBOL_VISIBLE sp_counted_base
0109 {
0110 private:
0111
0112 sp_counted_base( sp_counted_base const & );
0113 sp_counted_base & operator= ( sp_counted_base const & );
0114
0115 int use_count_;
0116 int weak_count_;
0117
0118 public:
0119
0120 sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
0121 {
0122 }
0123
0124 virtual ~sp_counted_base()
0125 {
0126 }
0127
0128
0129
0130
0131 virtual void dispose() = 0;
0132
0133
0134
0135 virtual void destroy()
0136 {
0137 delete this;
0138 }
0139
0140 virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
0141 virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
0142 virtual void * get_untyped_deleter() = 0;
0143
0144 void add_ref_copy()
0145 {
0146 atomic_increment( &use_count_ );
0147 }
0148
0149 bool add_ref_lock()
0150 {
0151 return atomic_conditional_increment( &use_count_ ) != 0;
0152 }
0153
0154 void release()
0155 {
0156 if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
0157 {
0158 dispose();
0159 weak_release();
0160 }
0161 }
0162
0163 void weak_add_ref()
0164 {
0165 atomic_increment( &weak_count_ );
0166 }
0167
0168 void weak_release()
0169 {
0170 if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
0171 {
0172 destroy();
0173 }
0174 }
0175
0176 long use_count() const
0177 {
0178 return static_cast<int const volatile &>( use_count_ );
0179 }
0180 };
0181
0182 }
0183
0184 }
0185
0186 #endif