1 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED 2 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_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_spin.hpp - spinlock pool atomic emulation 12 // 13 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 14 // Copyright 2004-2008 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 #include <boost/detail/sp_typeinfo.hpp> 22 #include <boost/smart_ptr/detail/spinlock_pool.hpp> 23 24 namespace boost 25 { 26 27 namespace detail 28 { 29 atomic_exchange_and_add(int * pw,int dv)30inline int atomic_exchange_and_add( int * pw, int dv ) 31 { 32 spinlock_pool<1>::scoped_lock lock( pw ); 33 34 int r = *pw; 35 *pw += dv; 36 return r; 37 } 38 atomic_increment(int * pw)39inline void atomic_increment( int * pw ) 40 { 41 spinlock_pool<1>::scoped_lock lock( pw ); 42 ++*pw; 43 } 44 atomic_conditional_increment(int * pw)45inline int atomic_conditional_increment( int * pw ) 46 { 47 spinlock_pool<1>::scoped_lock lock( pw ); 48 49 int rv = *pw; 50 if( rv != 0 ) ++*pw; 51 return rv; 52 } 53 54 class sp_counted_base 55 { 56 private: 57 58 sp_counted_base( sp_counted_base const & ); 59 sp_counted_base & operator= ( sp_counted_base const & ); 60 61 int use_count_; // #shared 62 int weak_count_; // #weak + (#shared != 0) 63 64 public: 65 sp_counted_base()66 sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) 67 { 68 } 69 ~sp_counted_base()70 virtual ~sp_counted_base() // nothrow 71 { 72 } 73 74 // dispose() is called when use_count_ drops to zero, to release 75 // the resources managed by *this. 76 77 virtual void dispose() = 0; // nothrow 78 79 // destroy() is called when weak_count_ drops to zero. 80 destroy()81 virtual void destroy() // nothrow 82 { 83 delete this; 84 } 85 86 virtual void * get_deleter( sp_typeinfo const & ti ) = 0; 87 virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; 88 virtual void * get_untyped_deleter() = 0; 89 add_ref_copy()90 void add_ref_copy() 91 { 92 atomic_increment( &use_count_ ); 93 } 94 add_ref_lock()95 bool add_ref_lock() // true on success 96 { 97 return atomic_conditional_increment( &use_count_ ) != 0; 98 } 99 release()100 void release() // nothrow 101 { 102 if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) 103 { 104 dispose(); 105 weak_release(); 106 } 107 } 108 weak_add_ref()109 void weak_add_ref() // nothrow 110 { 111 atomic_increment( &weak_count_ ); 112 } 113 weak_release()114 void weak_release() // nothrow 115 { 116 if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) 117 { 118 destroy(); 119 } 120 } 121 use_count() const122 long use_count() const // nothrow 123 { 124 spinlock_pool<1>::scoped_lock lock( &use_count_ ); 125 return use_count_; 126 } 127 }; 128 129 } // namespace detail 130 131 } // namespace boost 132 133 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED 134