1 #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
2 #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
9 // detail/shared_count.hpp
11 // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
13 // Permission to copy, use, modify, sell and distribute this software
14 // is granted provided this copyright notice appears in all copies.
15 // This software is provided "as is" without express or implied
16 // warranty, and with no claim as to its suitability for any purpose.
19 #include <boost/config.hpp>
21 #ifndef BOOST_NO_AUTO_PTR
25 #include <boost/checked_delete.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/detail/lightweight_mutex.hpp>
29 #include <functional> // for std::less
30 #include <exception> // for std::exception
31 #include <new> // for std::bad_alloc
34 # pragma warn -8026 // Functions with excep. spec. are not expanded inline
35 # pragma warn -8027 // Functions containing try are not expanded inline
41 // The standard library that comes with Borland C++ 5.5.1
42 // defines std::exception and its members as having C calling
43 // convention (-pc). When the definition of use_count_is_zero
44 // is compiled with -ps, the compiler issues an error.
45 // Hence, the temporary #pragma option -pc below. The version
46 // check is deliberately conservative.
48 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
49 # pragma option push -pc
52 class use_count_is_zero: public std::exception
56 virtual char const * what() const throw()
58 return "boost::use_count_is_zero";
62 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
70 typedef detail::lightweight_mutex mutex_type;
75 use_count_(0), weak_count_(0)
79 // pre: initial_use_count <= initial_weak_count
81 explicit counted_base(long initial_use_count, long initial_weak_count):
82 use_count_(initial_use_count), weak_count_(initial_weak_count)
86 virtual ~counted_base() // nothrow
90 // dispose() is called when use_count_ drops to zero, to release
91 // the resources managed by *this.
93 // counted_base doesn't manage any resources except itself, and
94 // the default implementation is a no-op.
96 // dispose() is not pure virtual since weak_ptr instantiates a
97 // counted_base in its default constructor.
99 virtual void dispose() // nothrow
103 // destruct() is called when weak_count_ drops to zero.
105 virtual void destruct() // nothrow
112 #ifdef BOOST_HAS_THREADS
113 mutex_type::scoped_lock lock(mtx_);
115 if(use_count_ == 0 && weak_count_ != 0) boost::throw_exception(boost::use_count_is_zero());
120 void release() // nothrow
126 #ifdef BOOST_HAS_THREADS
127 mutex_type::scoped_lock lock(mtx_);
129 new_use_count = --use_count_;
130 new_weak_count = --weak_count_;
133 if(new_use_count == 0)
138 if(new_weak_count == 0)
144 void weak_add_ref() // nothrow
146 #ifdef BOOST_HAS_THREADS
147 mutex_type::scoped_lock lock(mtx_);
152 void weak_release() // nothrow
157 #ifdef BOOST_HAS_THREADS
158 mutex_type::scoped_lock lock(mtx_);
160 new_weak_count = --weak_count_;
163 if(new_weak_count == 0)
169 long use_count() const // nothrow
171 #ifdef BOOST_HAS_THREADS
172 mutex_type::scoped_lock lock(mtx_);
179 counted_base(counted_base const &);
180 counted_base & operator= (counted_base const &);
182 // inv: use_count_ <= weak_count_
187 #ifdef BOOST_HAS_THREADS
188 mutable mutex_type mtx_;
192 inline void intrusive_ptr_add_ref(counted_base * p)
197 inline void intrusive_ptr_release(counted_base * p)
206 // Borland's Codeguard trips up over the -Vx- option here:
209 #pragma option push -Vx-
212 template<class P, class D> class counted_base_impl: public counted_base
216 P ptr; // copy constructor must not throw
217 D del; // copy constructor must not throw
219 counted_base_impl(counted_base_impl const &);
220 counted_base_impl & operator= (counted_base_impl const &);
224 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
226 counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
227 counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
231 virtual void dispose() // nothrow
245 friend class weak_count;
247 template<class P, class D> shared_count(P, D, counted_base const *);
251 shared_count(): pi_(new counted_base(1, 1))
255 explicit shared_count(counted_base * pi): pi_(pi) // never throws
260 template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
262 #ifndef BOOST_NO_EXCEPTIONS
266 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
276 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
281 boost::throw_exception(std::bad_alloc());
287 template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
292 #ifndef BOOST_NO_AUTO_PTR
294 // auto_ptr<Y> is special cased to provide the strong guarantee
297 explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
304 ~shared_count() // nothrow
309 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
314 explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
316 shared_count & operator= (shared_count const & r) // nothrow
318 counted_base * tmp = r.pi_;
326 void swap(shared_count & r) // nothrow
328 counted_base * tmp = r.pi_;
333 long use_count() const // nothrow
335 return pi_->use_count();
338 bool unique() const // nothrow
340 return pi_->use_count() == 1;
343 friend inline bool operator==(shared_count const & a, shared_count const & b)
345 return a.pi_ == b.pi_;
348 friend inline bool operator<(shared_count const & a, shared_count const & b)
350 return std::less<counted_base *>()(a.pi_, b.pi_);
365 friend class shared_count;
369 weak_count(): pi_(new counted_base(0, 1)) // can throw
373 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
378 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
383 ~weak_count() // nothrow
388 weak_count & operator= (shared_count const & r) // nothrow
390 counted_base * tmp = r.pi_;
398 weak_count & operator= (weak_count const & r) // nothrow
400 counted_base * tmp = r.pi_;
408 void swap(weak_count & r) // nothrow
410 counted_base * tmp = r.pi_;
415 long use_count() const // nothrow
417 return pi_->use_count();
420 friend inline bool operator==(weak_count const & a, weak_count const & b)
422 return a.pi_ == b.pi_;
425 friend inline bool operator<(weak_count const & a, weak_count const & b)
427 return std::less<counted_base *>()(a.pi_, b.pi_);
431 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
436 } // namespace detail
441 # pragma warn .8027 // Functions containing try are not expanded inline
442 # pragma warn .8026 // Functions with excep. spec. are not expanded inline
445 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED