CppCMS
|
00001 #ifndef BOOSTER_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED 00002 #define BOOSTER_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED 00003 // 00004 // detail/shared_count.hpp 00005 // 00006 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 00007 // Copyright 2004-2005 Peter Dimov 00008 // 00009 // Distributed under the Boost Software License, Version 1.0. (See 00010 // accompanying file LICENSE_1_0.txt or copy at 00011 // http://www.boost.org/LICENSE_1_0.txt) 00012 // 00013 00014 #ifdef __BORLANDC__ 00015 # pragma warn -8027 // Functions containing try are not expanded inline 00016 #endif 00017 00018 #include <booster/config.h> 00019 #include <booster/checked_delete.h> 00020 #include <booster/bad_weak_ptr.h> 00021 #include <booster/smart_ptr/sp_counted_base.h> 00022 #include <booster/smart_ptr/sp_counted_impl.h> 00023 #include <memory> 00024 #include <functional> // std::less 00025 #include <new> // std::bad_alloc 00026 00027 namespace booster 00028 { 00029 00030 namespace detail 00031 { 00032 00033 struct sp_nothrow_tag {}; 00034 00035 class weak_count; 00036 00037 class shared_count 00038 { 00039 private: 00040 00041 sp_counted_base * pi_; 00042 00043 friend class weak_count; 00044 00045 public: 00046 00047 shared_count(): pi_(0) // nothrow 00048 { 00049 } 00050 00051 template<class Y> explicit shared_count( Y * p ): pi_( 0 ) 00052 { 00053 try 00054 { 00055 pi_ = new sp_counted_impl_p<Y>( p ); 00056 } 00057 catch(...) 00058 { 00059 booster::checked_delete( p ); 00060 throw; 00061 } 00062 } 00063 00064 template<class P, class D> shared_count( P p, D d ): pi_(0) 00065 { 00066 try 00067 { 00068 pi_ = new sp_counted_impl_pd<P, D>(p, d); 00069 } 00070 catch(...) 00071 { 00072 d(p); // delete p 00073 throw; 00074 } 00075 } 00076 00077 template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 ) 00078 { 00079 typedef sp_counted_impl_pda<P, D, A> impl_type; 00080 typedef typename A::template rebind< impl_type >::other A2; 00081 00082 A2 a2( a ); 00083 00084 try 00085 { 00086 pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); 00087 new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); 00088 } 00089 catch(...) 00090 { 00091 d( p ); 00092 00093 if( pi_ != 0 ) 00094 { 00095 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); 00096 } 00097 00098 throw; 00099 } 00100 00101 } 00102 00103 // auto_ptr<Y> is special cased to provide the strong guarantee 00104 00105 template<class Y> 00106 explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) ) 00107 { 00108 00109 r.release(); 00110 } 00111 00112 00113 ~shared_count() // nothrow 00114 { 00115 if( pi_ != 0 ) pi_->release(); 00116 } 00117 00118 shared_count(shared_count const & r): pi_(r.pi_) // nothrow 00119 { 00120 if( pi_ != 0 ) pi_->add_ref_copy(); 00121 } 00122 00123 explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 00124 shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 00125 00126 shared_count & operator= (shared_count const & r) // nothrow 00127 { 00128 sp_counted_base * tmp = r.pi_; 00129 00130 if( tmp != pi_ ) 00131 { 00132 if( tmp != 0 ) tmp->add_ref_copy(); 00133 if( pi_ != 0 ) pi_->release(); 00134 pi_ = tmp; 00135 } 00136 00137 return *this; 00138 } 00139 00140 void swap(shared_count & r) // nothrow 00141 { 00142 sp_counted_base * tmp = r.pi_; 00143 r.pi_ = pi_; 00144 pi_ = tmp; 00145 } 00146 00147 long use_count() const // nothrow 00148 { 00149 return pi_ != 0? pi_->use_count(): 0; 00150 } 00151 00152 bool unique() const // nothrow 00153 { 00154 return use_count() == 1; 00155 } 00156 00157 bool empty() const // nothrow 00158 { 00159 return pi_ == 0; 00160 } 00161 00162 friend inline bool operator==(shared_count const & a, shared_count const & b) 00163 { 00164 return a.pi_ == b.pi_; 00165 } 00166 00167 friend inline bool operator<(shared_count const & a, shared_count const & b) 00168 { 00169 return std::less<sp_counted_base *>()( a.pi_, b.pi_ ); 00170 } 00171 00172 void * get_deleter( sp_typeinfo const & ti ) const 00173 { 00174 return pi_? pi_->get_deleter( ti ): 0; 00175 } 00176 }; 00177 00178 00179 class weak_count 00180 { 00181 private: 00182 00183 sp_counted_base * pi_; 00184 00185 friend class shared_count; 00186 00187 public: 00188 00189 weak_count(): pi_(0) // nothrow 00190 { 00191 } 00192 00193 weak_count(shared_count const & r): pi_(r.pi_) // nothrow 00194 { 00195 if(pi_ != 0) pi_->weak_add_ref(); 00196 } 00197 00198 weak_count(weak_count const & r): pi_(r.pi_) // nothrow 00199 { 00200 if(pi_ != 0) pi_->weak_add_ref(); 00201 } 00202 00203 00204 ~weak_count() // nothrow 00205 { 00206 if(pi_ != 0) pi_->weak_release(); 00207 } 00208 00209 weak_count & operator= (shared_count const & r) // nothrow 00210 { 00211 sp_counted_base * tmp = r.pi_; 00212 00213 if( tmp != pi_ ) 00214 { 00215 if(tmp != 0) tmp->weak_add_ref(); 00216 if(pi_ != 0) pi_->weak_release(); 00217 pi_ = tmp; 00218 } 00219 00220 return *this; 00221 } 00222 00223 weak_count & operator= (weak_count const & r) // nothrow 00224 { 00225 sp_counted_base * tmp = r.pi_; 00226 00227 if( tmp != pi_ ) 00228 { 00229 if(tmp != 0) tmp->weak_add_ref(); 00230 if(pi_ != 0) pi_->weak_release(); 00231 pi_ = tmp; 00232 } 00233 00234 return *this; 00235 } 00236 00237 void swap(weak_count & r) // nothrow 00238 { 00239 sp_counted_base * tmp = r.pi_; 00240 r.pi_ = pi_; 00241 pi_ = tmp; 00242 } 00243 00244 long use_count() const // nothrow 00245 { 00246 return pi_ != 0? pi_->use_count(): 0; 00247 } 00248 00249 bool empty() const // nothrow 00250 { 00251 return pi_ == 0; 00252 } 00253 00254 friend inline bool operator==(weak_count const & a, weak_count const & b) 00255 { 00256 return a.pi_ == b.pi_; 00257 } 00258 00259 friend inline bool operator<(weak_count const & a, weak_count const & b) 00260 { 00261 return std::less<sp_counted_base *>()(a.pi_, b.pi_); 00262 } 00263 }; 00264 00265 inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) 00266 { 00267 if( pi_ == 0 || !pi_->add_ref_lock() ) 00268 { 00269 throw booster::bad_weak_ptr(); 00270 } 00271 } 00272 00273 inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) 00274 { 00275 if( pi_ != 0 && !pi_->add_ref_lock() ) 00276 { 00277 pi_ = 0; 00278 } 00279 } 00280 00281 } // namespace detail 00282 00283 } // namespace boost 00284 00285 #ifdef __BORLANDC__ 00286 # pragma warn .8027 // Functions containing try are not expanded inline 00287 #endif 00288 00289 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED