src/sysc/packages/boost/detail/shared_count.hpp

Go to the documentation of this file.
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 //  detail/shared_count.hpp
00010 //
00011 //  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
00012 //
00013 //  Permission to copy, use, modify, sell and distribute this software
00014 //  is granted provided this copyright notice appears in all copies.
00015 //  This software is provided "as is" without express or implied
00016 //  warranty, and with no claim as to its suitability for any purpose.
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>       // for std::less
00030 #include <exception>        // for std::exception
00031 #include <new>              // for std::bad_alloc
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 // The standard library that comes with Borland C++ 5.5.1
00042 // defines std::exception and its members as having C calling
00043 // convention (-pc). When the definition of use_count_is_zero
00044 // is compiled with -ps, the compiler issues an error.
00045 // Hence, the temporary #pragma option -pc below. The version
00046 // check is deliberately conservative.
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     // pre: initial_use_count <= initial_weak_count
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() // nothrow
00087     {
00088     }
00089 
00090     // dispose() is called when use_count_ drops to zero, to release
00091     // the resources managed by *this.
00092     //
00093     // counted_base doesn't manage any resources except itself, and
00094     // the default implementation is a no-op.
00095     //
00096     // dispose() is not pure virtual since weak_ptr instantiates a
00097     // counted_base in its default constructor.
00098 
00099     virtual void dispose() // nothrow
00100     {
00101     }
00102 
00103     // destruct() is called when weak_count_ drops to zero.
00104 
00105     virtual void destruct() // nothrow
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() // nothrow
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() // nothrow
00145     {
00146 #ifdef BOOST_HAS_THREADS
00147         mutex_type::scoped_lock lock(mtx_);
00148 #endif
00149         ++weak_count_;
00150     }
00151 
00152     void weak_release() // nothrow
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 // nothrow
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     // inv: use_count_ <= weak_count_
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 // Borland's Codeguard trips up over the -Vx- option here:
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; // copy constructor must not throw
00217     D del; // copy constructor must not throw
00218 
00219     counted_base_impl(counted_base_impl const &);
00220     counted_base_impl & operator= (counted_base_impl const &);
00221 
00222 public:
00223 
00224     // pre: initial_use_count <= initial_weak_count, d(p) must not throw
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() // nothrow
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) // never throws
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); // delete 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); // delete 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     // auto_ptr<Y> is special cased to provide the strong guarantee
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() // nothrow
00305     {
00306         pi_->release();
00307     }
00308 
00309     shared_count(shared_count const & r): pi_(r.pi_) // nothrow
00310     {
00311         pi_->add_ref();
00312     }
00313 
00314     explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
00315 
00316     shared_count & operator= (shared_count const & r) // nothrow
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) // nothrow
00327     {
00328         counted_base * tmp = r.pi_;
00329         r.pi_ = pi_;
00330         pi_ = tmp;
00331     }
00332 
00333     long use_count() const // nothrow
00334     {
00335         return pi_->use_count();
00336     }
00337 
00338     bool unique() const // nothrow
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)) // can throw
00370     {
00371     }
00372 
00373     weak_count(shared_count const & r): pi_(r.pi_) // nothrow
00374     {
00375         pi_->weak_add_ref();
00376     }
00377 
00378     weak_count(weak_count const & r): pi_(r.pi_) // nothrow
00379     {
00380         pi_->weak_add_ref();
00381     }
00382 
00383     ~weak_count() // nothrow
00384     {
00385         pi_->weak_release();
00386     }
00387 
00388     weak_count & operator= (shared_count const & r) // nothrow
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) // nothrow
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) // nothrow
00409     {
00410         counted_base * tmp = r.pi_;
00411         r.pi_ = pi_;
00412         pi_ = tmp;
00413     }
00414 
00415     long use_count() const // nothrow
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 } // namespace detail
00437 
00438 } // namespace boost
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

Generated on Wed Apr 25 13:53:28 2007 for SystemC by  doxygen 1.5.1