1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED 2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_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_sync.hpp - g++ 4.1+ __sync intrinsics 11 // 12 // Copyright (c) 2007 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/config.hpp> 20 #include <limits.h> 21 22 #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) 23 # include <ia64intrin.h> 24 #endif 25 26 #if defined(BOOST_SP_REPORT_IMPLEMENTATION) 27 28 #include <boost/config/pragma_message.hpp> 29 BOOST_PRAGMA_MESSAGE("Using __sync sp_counted_base") 30 31 #endif 32 33 namespace boost 34 { 35 36 namespace detail 37 { 38 39 #if INT_MAX >= 2147483647 40 41 typedef int sp_int32_t; 42 43 #else 44 45 typedef long sp_int32_t; 46 47 #endif 48 atomic_increment(sp_int32_t * pw)49inline void atomic_increment( sp_int32_t * pw ) 50 { 51 __sync_fetch_and_add( pw, 1 ); 52 } 53 atomic_decrement(sp_int32_t * pw)54inline sp_int32_t atomic_decrement( sp_int32_t * pw ) 55 { 56 return __sync_fetch_and_add( pw, -1 ); 57 } 58 atomic_conditional_increment(sp_int32_t * pw)59inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) 60 { 61 // long r = *pw; 62 // if( r != 0 ) ++*pw; 63 // return r; 64 65 sp_int32_t r = *pw; 66 67 for( ;; ) 68 { 69 if( r == 0 ) 70 { 71 return r; 72 } 73 74 sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); 75 76 if( r2 == r ) 77 { 78 return r; 79 } 80 else 81 { 82 r = r2; 83 } 84 } 85 } 86 87 class BOOST_SYMBOL_VISIBLE sp_counted_base 88 { 89 private: 90 91 sp_counted_base( sp_counted_base const & ); 92 sp_counted_base & operator= ( sp_counted_base const & ); 93 94 sp_int32_t use_count_; // #shared 95 sp_int32_t weak_count_; // #weak + (#shared != 0) 96 97 public: 98 sp_counted_base()99 sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) 100 { 101 } 102 ~sp_counted_base()103 virtual ~sp_counted_base() // nothrow 104 { 105 } 106 107 // dispose() is called when use_count_ drops to zero, to release 108 // the resources managed by *this. 109 110 virtual void dispose() = 0; // nothrow 111 112 // destroy() is called when weak_count_ drops to zero. 113 destroy()114 virtual void destroy() // nothrow 115 { 116 delete this; 117 } 118 119 virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; 120 virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; 121 virtual void * get_untyped_deleter() = 0; 122 add_ref_copy()123 void add_ref_copy() 124 { 125 atomic_increment( &use_count_ ); 126 } 127 add_ref_lock()128 bool add_ref_lock() // true on success 129 { 130 return atomic_conditional_increment( &use_count_ ) != 0; 131 } 132 release()133 void release() // nothrow 134 { 135 if( atomic_decrement( &use_count_ ) == 1 ) 136 { 137 dispose(); 138 weak_release(); 139 } 140 } 141 weak_add_ref()142 void weak_add_ref() // nothrow 143 { 144 atomic_increment( &weak_count_ ); 145 } 146 weak_release()147 void weak_release() // nothrow 148 { 149 if( atomic_decrement( &weak_count_ ) == 1 ) 150 { 151 destroy(); 152 } 153 } 154 use_count() const155 long use_count() const // nothrow 156 { 157 return const_cast< sp_int32_t const volatile & >( use_count_ ); 158 } 159 }; 160 161 } // namespace detail 162 163 } // namespace boost 164 165 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED 166