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