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/detail/lightweight_mutex.hpp>
28 #include <functional> // for std::less
29 #include <exception> // for std::exception
34 class use_count_is_zero: public std::exception
38 virtual char const * what() const throw()
40 return "use_count_is_zero";
48 typedef detail::lightweight_mutex mutex_type;
53 use_count_(0), weak_count_(0), self_deleter_(&self_delete)
57 // pre: initial_use_count <= initial_weak_count
59 explicit counted_base(long initial_use_count, long initial_weak_count):
60 use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
64 virtual ~counted_base() // nothrow
68 // dispose() is called when use_count_ drops to zero, to release
69 // the resources managed by *this.
71 // counted_base doesn't manage any resources except itself, and
72 // the default implementation is a no-op.
74 // dispose() is not pure virtual since weak_ptr instantiates a
75 // counted_base in its default constructor.
77 virtual void dispose() // nothrow
83 #ifdef BOOST_HAS_THREADS
84 mutex_type::scoped_lock lock(mtx_);
86 if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
91 void release() // nothrow
97 #ifdef BOOST_HAS_THREADS
98 mutex_type::scoped_lock lock(mtx_);
100 new_use_count = --use_count_;
101 new_weak_count = --weak_count_;
104 if(new_use_count == 0)
109 if(new_weak_count == 0)
111 // not a direct 'delete this', because the inlined
112 // release() may use a different heap manager
117 void weak_add_ref() // nothrow
119 #ifdef BOOST_HAS_THREADS
120 mutex_type::scoped_lock lock(mtx_);
125 void weak_release() // nothrow
130 #ifdef BOOST_HAS_THREADS
131 mutex_type::scoped_lock lock(mtx_);
133 new_weak_count = --weak_count_;
136 if(new_weak_count == 0)
142 long use_count() const // nothrow
144 #ifdef BOOST_HAS_THREADS
145 mutex_type::scoped_lock lock(mtx_);
152 counted_base(counted_base const &);
153 counted_base & operator= (counted_base const &);
155 static void self_delete(counted_base * p)
160 // inv: use_count_ <= weak_count_
164 #ifdef BOOST_HAS_THREADS
165 mutable mutex_type mtx_;
167 void (*self_deleter_) (counted_base *);
170 inline void intrusive_ptr_add_ref(counted_base * p)
175 inline void intrusive_ptr_release(counted_base * p)
183 template<class P, class D> class counted_base_impl: public counted_base
187 P ptr; // copy constructor must not throw
188 D del; // copy constructor must not throw
190 counted_base_impl(counted_base_impl const &);
191 counted_base_impl & operator= (counted_base_impl const &);
195 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
197 counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
198 counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
202 virtual void dispose() // nothrow
216 friend class weak_count;
218 template<class P, class D> shared_count(P, D, counted_base const *);
222 shared_count(): pi_(new counted_base(1, 1))
226 explicit shared_count(counted_base * pi): pi_(pi) // never throws
231 template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
235 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
244 template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
249 #ifndef BOOST_NO_AUTO_PTR
251 // auto_ptr<Y> is special cased to provide the strong guarantee
254 explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
261 ~shared_count() // nothrow
266 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
271 explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
273 shared_count & operator= (shared_count const & r) // nothrow
275 counted_base * tmp = r.pi_;
283 void swap(shared_count & r) // nothrow
285 counted_base * tmp = r.pi_;
290 long use_count() const // nothrow
292 return pi_->use_count();
295 bool unique() const // nothrow
297 return pi_->use_count() == 1;
300 friend inline bool operator==(shared_count const & a, shared_count const & b)
302 return a.pi_ == b.pi_;
305 friend inline bool operator<(shared_count const & a, shared_count const & b)
307 return std::less<counted_base *>()(a.pi_, b.pi_);
317 friend class shared_count;
321 weak_count(): pi_(new counted_base(0, 1)) // can throw
325 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
330 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
335 ~weak_count() // nothrow
340 weak_count & operator= (shared_count const & r) // nothrow
342 counted_base * tmp = r.pi_;
350 weak_count & operator= (weak_count const & r) // nothrow
352 counted_base * tmp = r.pi_;
360 void swap(weak_count & r) // nothrow
362 counted_base * tmp = r.pi_;
367 long use_count() const // nothrow
369 return pi_->use_count();
372 friend inline bool operator==(weak_count const & a, weak_count const & b)
374 return a.pi_ == b.pi_;
377 friend inline bool operator<(weak_count const & a, weak_count const & b)
379 return std::less<counted_base *>()(a.pi_, b.pi_);
383 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
388 } // namespace detail
392 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED