1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED 2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_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 // 11 // detail/sp_counted_base_w32.hpp 12 // 13 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 14 // Copyright 2004-2005 Peter Dimov 15 // 16 // Distributed under the Boost Software License, Version 1.0. (See 17 // accompanying file LICENSE_1_0.txt or copy at 18 // http://www.boost.org/LICENSE_1_0.txt) 19 // 20 // 21 // Lock-free algorithm by Alexander Terekhov 22 // 23 // Thanks to Ben Hitchings for the #weak + (#shared != 0) 24 // formulation 25 // 26 27 #include <boost/smart_ptr/detail/sp_interlocked.hpp> 28 #include <boost/detail/workaround.hpp> 29 #include <boost/detail/sp_typeinfo.hpp> 30 31 namespace boost 32 { 33 34 namespace detail 35 { 36 37 class sp_counted_base 38 { 39 private: 40 41 sp_counted_base( sp_counted_base const & ); 42 sp_counted_base & operator= ( sp_counted_base const & ); 43 44 long use_count_; // #shared 45 long weak_count_; // #weak + (#shared != 0) 46 47 public: 48 sp_counted_base()49 sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) 50 { 51 } 52 ~sp_counted_base()53 virtual ~sp_counted_base() // nothrow 54 { 55 } 56 57 // dispose() is called when use_count_ drops to zero, to release 58 // the resources managed by *this. 59 60 virtual void dispose() = 0; // nothrow 61 62 // destroy() is called when weak_count_ drops to zero. 63 destroy()64 virtual void destroy() // nothrow 65 { 66 delete this; 67 } 68 69 virtual void * get_deleter( sp_typeinfo const & ti ) = 0; 70 virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; 71 virtual void * get_untyped_deleter() = 0; 72 add_ref_copy()73 void add_ref_copy() 74 { 75 BOOST_SP_INTERLOCKED_INCREMENT( &use_count_ ); 76 } 77 add_ref_lock()78 bool add_ref_lock() // true on success 79 { 80 for( ;; ) 81 { 82 long tmp = static_cast< long const volatile& >( use_count_ ); 83 if( tmp == 0 ) return false; 84 85 #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 ) 86 87 // work around a code generation bug 88 89 long tmp2 = tmp + 1; 90 if( BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true; 91 92 #else 93 94 if( BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; 95 96 #endif 97 } 98 } 99 release()100 void release() // nothrow 101 { 102 if( BOOST_SP_INTERLOCKED_DECREMENT( &use_count_ ) == 0 ) 103 { 104 dispose(); 105 weak_release(); 106 } 107 } 108 weak_add_ref()109 void weak_add_ref() // nothrow 110 { 111 BOOST_SP_INTERLOCKED_INCREMENT( &weak_count_ ); 112 } 113 weak_release()114 void weak_release() // nothrow 115 { 116 if( BOOST_SP_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 ) 117 { 118 destroy(); 119 } 120 } 121 use_count() const122 long use_count() const // nothrow 123 { 124 return static_cast<long const volatile &>( use_count_ ); 125 } 126 }; 127 128 } // namespace detail 129 130 } // namespace boost 131 132 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED 133