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