CppCMS
booster/smart_ptr/shared_count.h
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