00001 #ifndef BOOSTER_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
00002 #define BOOSTER_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
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>
00025 #include <new>
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)
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);
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
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()
00114 {
00115 if( pi_ != 0 ) pi_->release();
00116 }
00117
00118 shared_count(shared_count const & r): pi_(r.pi_)
00119 {
00120 if( pi_ != 0 ) pi_->add_ref_copy();
00121 }
00122
00123 explicit shared_count(weak_count const & r);
00124 shared_count( weak_count const & r, sp_nothrow_tag );
00125
00126 shared_count & operator= (shared_count const & r)
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)
00141 {
00142 sp_counted_base * tmp = r.pi_;
00143 r.pi_ = pi_;
00144 pi_ = tmp;
00145 }
00146
00147 long use_count() const
00148 {
00149 return pi_ != 0? pi_->use_count(): 0;
00150 }
00151
00152 bool unique() const
00153 {
00154 return use_count() == 1;
00155 }
00156
00157 bool empty() const
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)
00190 {
00191 }
00192
00193 weak_count(shared_count const & r): pi_(r.pi_)
00194 {
00195 if(pi_ != 0) pi_->weak_add_ref();
00196 }
00197
00198 weak_count(weak_count const & r): pi_(r.pi_)
00199 {
00200 if(pi_ != 0) pi_->weak_add_ref();
00201 }
00202
00203
00204 ~weak_count()
00205 {
00206 if(pi_ != 0) pi_->weak_release();
00207 }
00208
00209 weak_count & operator= (shared_count const & r)
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)
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)
00238 {
00239 sp_counted_base * tmp = r.pi_;
00240 r.pi_ = pi_;
00241 pi_ = tmp;
00242 }
00243
00244 long use_count() const
00245 {
00246 return pi_ != 0? pi_->use_count(): 0;
00247 }
00248
00249 bool empty() const
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 }
00282
00283 }
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