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