00001 #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED 00002 #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_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 // 00011 // detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation 00012 // 00013 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 00014 // Copyright 2004-2008 Peter Dimov 00015 // 00016 // Distributed under the Boost Software License, Version 1.0. (See 00017 // accompanying file LICENSE_1_0.txt or copy at 00018 // http://www.boost.org/LICENSE_1_0.txt) 00019 // 00020 00021 #include <boost/detail/sp_typeinfo.hpp> 00022 #include <boost/smart_ptr/detail/spinlock_pool.hpp> 00023 00024 namespace boost 00025 { 00026 00027 namespace detail 00028 { 00029 00030 inline int atomic_exchange_and_add( int * pw, int dv ) 00031 { 00032 spinlock_pool<1>::scoped_lock lock( pw ); 00033 00034 int r = *pw; 00035 *pw += dv; 00036 return r; 00037 } 00038 00039 inline void atomic_increment( int * pw ) 00040 { 00041 spinlock_pool<1>::scoped_lock lock( pw ); 00042 ++*pw; 00043 } 00044 00045 inline int atomic_conditional_increment( int * pw ) 00046 { 00047 spinlock_pool<1>::scoped_lock lock( pw ); 00048 00049 int rv = *pw; 00050 if( rv != 0 ) ++*pw; 00051 return rv; 00052 } 00053 00054 class sp_counted_base 00055 { 00056 private: 00057 00058 sp_counted_base( sp_counted_base const & ); 00059 sp_counted_base & operator= ( sp_counted_base const & ); 00060 00061 int use_count_; // #shared 00062 int weak_count_; // #weak + (#shared != 0) 00063 00064 public: 00065 00066 sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) 00067 { 00068 } 00069 00070 virtual ~sp_counted_base() // nothrow 00071 { 00072 } 00073 00074 // dispose() is called when use_count_ drops to zero, to release 00075 // the resources managed by *this. 00076 00077 virtual void dispose() = 0; // nothrow 00078 00079 // destroy() is called when weak_count_ drops to zero. 00080 00081 virtual void destroy() // nothrow 00082 { 00083 delete this; 00084 } 00085 00086 virtual void * get_deleter( sp_typeinfo const & ti ) = 0; 00087 00088 void add_ref_copy() 00089 { 00090 atomic_increment( &use_count_ ); 00091 } 00092 00093 bool add_ref_lock() // true on success 00094 { 00095 return atomic_conditional_increment( &use_count_ ) != 0; 00096 } 00097 00098 void release() // nothrow 00099 { 00100 if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) 00101 { 00102 dispose(); 00103 weak_release(); 00104 } 00105 } 00106 00107 void weak_add_ref() // nothrow 00108 { 00109 atomic_increment( &weak_count_ ); 00110 } 00111 00112 void weak_release() // nothrow 00113 { 00114 if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) 00115 { 00116 destroy(); 00117 } 00118 } 00119 00120 long use_count() const // nothrow 00121 { 00122 spinlock_pool<1>::scoped_lock lock( &use_count_ ); 00123 return use_count_; 00124 } 00125 }; 00126 00127 } // namespace detail 00128 00129 } // namespace boost 00130 00131 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED