00001 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED 00002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED 00003 00004 // MS compatible compilers support #pragma once 00005 00006 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 00007 # pragma once 00008 #endif 00009 00010 // detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics 00011 // 00012 // Copyright (c) 2007 Peter Dimov 00013 // 00014 // Distributed under the Boost Software License, Version 1.0. 00015 // See accompanying file LICENSE_1_0.txt or copy at 00016 // http://www.boost.org/LICENSE_1_0.txt 00017 00018 #include <boost/detail/sp_typeinfo.hpp> 00019 #include <limits.h> 00020 00021 #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) 00022 # include <ia64intrin.h> 00023 #endif 00024 00025 namespace boost 00026 { 00027 00028 namespace detail 00029 { 00030 00031 #if INT_MAX >= 2147483647 00032 00033 typedef int sp_int32_t; 00034 00035 #else 00036 00037 typedef long sp_int32_t; 00038 00039 #endif 00040 00041 inline void atomic_increment( sp_int32_t * pw ) 00042 { 00043 __sync_fetch_and_add( pw, 1 ); 00044 } 00045 00046 inline sp_int32_t atomic_decrement( sp_int32_t * pw ) 00047 { 00048 return __sync_fetch_and_add( pw, -1 ); 00049 } 00050 00051 inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) 00052 { 00053 // long r = *pw; 00054 // if( r != 0 ) ++*pw; 00055 // return r; 00056 00057 sp_int32_t r = *pw; 00058 00059 for( ;; ) 00060 { 00061 if( r == 0 ) 00062 { 00063 return r; 00064 } 00065 00066 sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); 00067 00068 if( r2 == r ) 00069 { 00070 return r; 00071 } 00072 else 00073 { 00074 r = r2; 00075 } 00076 } 00077 } 00078 00079 class sp_counted_base 00080 { 00081 private: 00082 00083 sp_counted_base( sp_counted_base const & ); 00084 sp_counted_base & operator= ( sp_counted_base const & ); 00085 00086 sp_int32_t use_count_; // #shared 00087 sp_int32_t weak_count_; // #weak + (#shared != 0) 00088 00089 public: 00090 00091 sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) 00092 { 00093 } 00094 00095 virtual ~sp_counted_base() // nothrow 00096 { 00097 } 00098 00099 // dispose() is called when use_count_ drops to zero, to release 00100 // the resources managed by *this. 00101 00102 virtual void dispose() = 0; // nothrow 00103 00104 // destroy() is called when weak_count_ drops to zero. 00105 00106 virtual void destroy() // nothrow 00107 { 00108 delete this; 00109 } 00110 00111 virtual void * get_deleter( sp_typeinfo const & ti ) = 0; 00112 00113 void add_ref_copy() 00114 { 00115 atomic_increment( &use_count_ ); 00116 } 00117 00118 bool add_ref_lock() // true on success 00119 { 00120 return atomic_conditional_increment( &use_count_ ) != 0; 00121 } 00122 00123 void release() // nothrow 00124 { 00125 if( atomic_decrement( &use_count_ ) == 1 ) 00126 { 00127 dispose(); 00128 weak_release(); 00129 } 00130 } 00131 00132 void weak_add_ref() // nothrow 00133 { 00134 atomic_increment( &weak_count_ ); 00135 } 00136 00137 void weak_release() // nothrow 00138 { 00139 if( atomic_decrement( &weak_count_ ) == 1 ) 00140 { 00141 destroy(); 00142 } 00143 } 00144 00145 long use_count() const // nothrow 00146 { 00147 return const_cast< sp_int32_t const volatile & >( use_count_ ); 00148 } 00149 }; 00150 00151 } // namespace detail 00152 00153 } // namespace boost 00154 00155 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED