Go to the documentation of this file.00001 #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
00002 #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
00003
00004
00005
00006 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00007 # pragma once
00008 #endif
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef __BORLANDC__
00022 # pragma warn -8027 // Functions containing try are not expanded inline
00023 #endif
00024
00025 #include <boost/config.hpp>
00026 #include <boost/checked_delete.hpp>
00027 #include <boost/throw_exception.hpp>
00028 #include <boost/smart_ptr/bad_weak_ptr.hpp>
00029 #include <boost/smart_ptr/detail/sp_counted_base.hpp>
00030 #include <boost/smart_ptr/detail/sp_counted_impl.hpp>
00031 #include <boost/detail/workaround.hpp>
00032
00033
00034
00035
00036 #include <boost/config/no_tr1/memory.hpp>
00037 #include <functional>
00038 #include <new>
00039
00040 namespace boost
00041 {
00042
00043 namespace detail
00044 {
00045
00046 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00047
00048 int const shared_count_id = 0x2C35F101;
00049 int const weak_count_id = 0x298C38A4;
00050
00051 #endif
00052
00053 struct sp_nothrow_tag {};
00054
00055 class weak_count;
00056
00057 class shared_count
00058 {
00059 private:
00060
00061 sp_counted_base * pi_;
00062
00063 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00064 int id_;
00065 #endif
00066
00067 friend class weak_count;
00068
00069 public:
00070
00071 shared_count(): pi_(0)
00072 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00073 , id_(shared_count_id)
00074 #endif
00075 {
00076 }
00077
00078 template<class Y> explicit shared_count( Y * p ): pi_( 0 )
00079 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00080 , id_(shared_count_id)
00081 #endif
00082 {
00083 #ifndef BOOST_NO_EXCEPTIONS
00084
00085 try
00086 {
00087 pi_ = new sp_counted_impl_p<Y>( p );
00088 }
00089 catch(...)
00090 {
00091 boost::checked_delete( p );
00092 throw;
00093 }
00094
00095 #else
00096
00097 pi_ = new sp_counted_impl_p<Y>( p );
00098
00099 if( pi_ == 0 )
00100 {
00101 boost::checked_delete( p );
00102 boost::throw_exception( std::bad_alloc() );
00103 }
00104
00105 #endif
00106 }
00107
00108 #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
00109 template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
00110 #else
00111 template<class P, class D> shared_count( P p, D d ): pi_(0)
00112 #endif
00113 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00114 , id_(shared_count_id)
00115 #endif
00116 {
00117 #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
00118 typedef Y* P;
00119 #endif
00120 #ifndef BOOST_NO_EXCEPTIONS
00121
00122 try
00123 {
00124 pi_ = new sp_counted_impl_pd<P, D>(p, d);
00125 }
00126 catch(...)
00127 {
00128 d(p);
00129 throw;
00130 }
00131
00132 #else
00133
00134 pi_ = new sp_counted_impl_pd<P, D>(p, d);
00135
00136 if(pi_ == 0)
00137 {
00138 d(p);
00139 boost::throw_exception(std::bad_alloc());
00140 }
00141
00142 #endif
00143 }
00144
00145 template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
00146 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00147 , id_(shared_count_id)
00148 #endif
00149 {
00150 typedef sp_counted_impl_pda<P, D, A> impl_type;
00151 typedef typename A::template rebind< impl_type >::other A2;
00152
00153 A2 a2( a );
00154
00155 #ifndef BOOST_NO_EXCEPTIONS
00156
00157 try
00158 {
00159 pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
00160 new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
00161 }
00162 catch(...)
00163 {
00164 d( p );
00165
00166 if( pi_ != 0 )
00167 {
00168 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
00169 }
00170
00171 throw;
00172 }
00173
00174 #else
00175
00176 pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
00177
00178 if( pi_ != 0 )
00179 {
00180 new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
00181 }
00182 else
00183 {
00184 d( p );
00185 boost::throw_exception( std::bad_alloc() );
00186 }
00187
00188 #endif
00189 }
00190
00191 #ifndef BOOST_NO_AUTO_PTR
00192
00193
00194
00195 template<class Y>
00196 explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
00197 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00198 , id_(shared_count_id)
00199 #endif
00200 {
00201 #ifdef BOOST_NO_EXCEPTIONS
00202
00203 if( pi_ == 0 )
00204 {
00205 boost::throw_exception(std::bad_alloc());
00206 }
00207
00208 #endif
00209
00210 r.release();
00211 }
00212
00213 #endif
00214
00215 ~shared_count()
00216 {
00217 if( pi_ != 0 ) pi_->release();
00218 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00219 id_ = 0;
00220 #endif
00221 }
00222
00223 shared_count(shared_count const & r): pi_(r.pi_)
00224 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00225 , id_(shared_count_id)
00226 #endif
00227 {
00228 if( pi_ != 0 ) pi_->add_ref_copy();
00229 }
00230
00231 #if defined( BOOST_HAS_RVALUE_REFS )
00232
00233 shared_count(shared_count && r): pi_(r.pi_)
00234 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00235 , id_(shared_count_id)
00236 #endif
00237 {
00238 r.pi_ = 0;
00239 }
00240
00241 #endif
00242
00243 explicit shared_count(weak_count const & r);
00244 shared_count( weak_count const & r, sp_nothrow_tag );
00245
00246 shared_count & operator= (shared_count const & r)
00247 {
00248 sp_counted_base * tmp = r.pi_;
00249
00250 if( tmp != pi_ )
00251 {
00252 if( tmp != 0 ) tmp->add_ref_copy();
00253 if( pi_ != 0 ) pi_->release();
00254 pi_ = tmp;
00255 }
00256
00257 return *this;
00258 }
00259
00260 void swap(shared_count & r)
00261 {
00262 sp_counted_base * tmp = r.pi_;
00263 r.pi_ = pi_;
00264 pi_ = tmp;
00265 }
00266
00267 long use_count() const
00268 {
00269 return pi_ != 0? pi_->use_count(): 0;
00270 }
00271
00272 bool unique() const
00273 {
00274 return use_count() == 1;
00275 }
00276
00277 bool empty() const
00278 {
00279 return pi_ == 0;
00280 }
00281
00282 friend inline bool operator==(shared_count const & a, shared_count const & b)
00283 {
00284 return a.pi_ == b.pi_;
00285 }
00286
00287 friend inline bool operator<(shared_count const & a, shared_count const & b)
00288 {
00289 return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
00290 }
00291
00292 void * get_deleter( sp_typeinfo const & ti ) const
00293 {
00294 return pi_? pi_->get_deleter( ti ): 0;
00295 }
00296 };
00297
00298
00299 class weak_count
00300 {
00301 private:
00302
00303 sp_counted_base * pi_;
00304
00305 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00306 int id_;
00307 #endif
00308
00309 friend class shared_count;
00310
00311 public:
00312
00313 weak_count(): pi_(0)
00314 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00315 , id_(weak_count_id)
00316 #endif
00317 {
00318 }
00319
00320 weak_count(shared_count const & r): pi_(r.pi_)
00321 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00322 , id_(weak_count_id)
00323 #endif
00324 {
00325 if(pi_ != 0) pi_->weak_add_ref();
00326 }
00327
00328 weak_count(weak_count const & r): pi_(r.pi_)
00329 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00330 , id_(weak_count_id)
00331 #endif
00332 {
00333 if(pi_ != 0) pi_->weak_add_ref();
00334 }
00335
00336 ~weak_count()
00337 {
00338 if(pi_ != 0) pi_->weak_release();
00339 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00340 id_ = 0;
00341 #endif
00342 }
00343
00344 weak_count & operator= (shared_count const & r)
00345 {
00346 sp_counted_base * tmp = r.pi_;
00347
00348 if( tmp != pi_ )
00349 {
00350 if(tmp != 0) tmp->weak_add_ref();
00351 if(pi_ != 0) pi_->weak_release();
00352 pi_ = tmp;
00353 }
00354
00355 return *this;
00356 }
00357
00358 weak_count & operator= (weak_count const & r)
00359 {
00360 sp_counted_base * tmp = r.pi_;
00361
00362 if( tmp != pi_ )
00363 {
00364 if(tmp != 0) tmp->weak_add_ref();
00365 if(pi_ != 0) pi_->weak_release();
00366 pi_ = tmp;
00367 }
00368
00369 return *this;
00370 }
00371
00372 void swap(weak_count & r)
00373 {
00374 sp_counted_base * tmp = r.pi_;
00375 r.pi_ = pi_;
00376 pi_ = tmp;
00377 }
00378
00379 long use_count() const
00380 {
00381 return pi_ != 0? pi_->use_count(): 0;
00382 }
00383
00384 bool empty() const
00385 {
00386 return pi_ == 0;
00387 }
00388
00389 friend inline bool operator==(weak_count const & a, weak_count const & b)
00390 {
00391 return a.pi_ == b.pi_;
00392 }
00393
00394 friend inline bool operator<(weak_count const & a, weak_count const & b)
00395 {
00396 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
00397 }
00398 };
00399
00400 inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
00401 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00402 , id_(shared_count_id)
00403 #endif
00404 {
00405 if( pi_ == 0 || !pi_->add_ref_lock() )
00406 {
00407 boost::throw_exception( boost::bad_weak_ptr() );
00408 }
00409 }
00410
00411 inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
00412 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
00413 , id_(shared_count_id)
00414 #endif
00415 {
00416 if( pi_ != 0 && !pi_->add_ref_lock() )
00417 {
00418 pi_ = 0;
00419 }
00420 }
00421
00422 }
00423
00424 }
00425
00426 #ifdef __BORLANDC__
00427 # pragma warn .8027 // Functions containing try are not expanded inline
00428 #endif
00429
00430 #endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED