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 #ifndef BOOST_NO_EXCEPTIONS
87 if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
89 BOOST_NOEH_ASSERT(!(use_count_ == 0 && weak_count_ != 0));
94 void release() // nothrow
100 #ifdef BOOST_HAS_THREADS
101 mutex_type::scoped_lock lock(mtx_);
103 new_use_count = --use_count_;
104 new_weak_count = --weak_count_;
107 if(new_use_count == 0)
112 if(new_weak_count == 0)
114 // not a direct 'delete this', because the inlined
115 // release() may use a different heap manager
120 void weak_add_ref() // nothrow
122 #ifdef BOOST_HAS_THREADS
123 mutex_type::scoped_lock lock(mtx_);
128 void weak_release() // nothrow
133 #ifdef BOOST_HAS_THREADS
134 mutex_type::scoped_lock lock(mtx_);
136 new_weak_count = --weak_count_;
139 if(new_weak_count == 0)
145 long use_count() const // nothrow
147 #ifdef BOOST_HAS_THREADS
148 mutex_type::scoped_lock lock(mtx_);
155 counted_base(counted_base const &);
156 counted_base & operator= (counted_base const &);
158 static void self_delete(counted_base * p)
163 // inv: use_count_ <= weak_count_
167 #ifdef BOOST_HAS_THREADS
168 mutable mutex_type mtx_;
170 void (*self_deleter_) (counted_base *);
173 inline void intrusive_ptr_add_ref(counted_base * p)
178 inline void intrusive_ptr_release(counted_base * p)
186 template<class P, class D> class counted_base_impl: public counted_base
190 P ptr; // copy constructor must not throw
191 D del; // copy constructor must not throw
193 counted_base_impl(counted_base_impl const &);
194 counted_base_impl & operator= (counted_base_impl const &);
198 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
200 counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
201 counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
205 virtual void dispose() // nothrow
219 friend class weak_count;
221 template<class P, class D> shared_count(P, D, counted_base const *);
225 shared_count(): pi_(new counted_base(1, 1))
229 explicit shared_count(counted_base * pi): pi_(pi) // never throws
234 template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
238 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
243 #ifndef BOOST_NO_EXCEPTIONS
246 BOOST_NOEH_ASSERT(false);
250 template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
255 #ifndef BOOST_NO_AUTO_PTR
257 // auto_ptr<Y> is special cased to provide the strong guarantee
260 explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
267 ~shared_count() // nothrow
272 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
277 explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
279 shared_count & operator= (shared_count const & r) // nothrow
281 counted_base * tmp = r.pi_;
289 void swap(shared_count & r) // nothrow
291 counted_base * tmp = r.pi_;
296 long use_count() const // nothrow
298 return pi_->use_count();
301 bool unique() const // nothrow
303 return pi_->use_count() == 1;
306 friend inline bool operator==(shared_count const & a, shared_count const & b)
308 return a.pi_ == b.pi_;
311 friend inline bool operator<(shared_count const & a, shared_count const & b)
313 return std::less<counted_base *>()(a.pi_, b.pi_);
323 friend class shared_count;
327 weak_count(): pi_(new counted_base(0, 1)) // can throw
331 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
336 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
341 ~weak_count() // nothrow
346 weak_count & operator= (shared_count const & r) // nothrow
348 counted_base * tmp = r.pi_;
356 weak_count & operator= (weak_count const & r) // nothrow
358 counted_base * tmp = r.pi_;
366 void swap(weak_count & r) // nothrow
368 counted_base * tmp = r.pi_;
373 long use_count() const // nothrow
375 return pi_->use_count();
378 friend inline bool operator==(weak_count const & a, weak_count const & b)
380 return a.pi_ == b.pi_;
383 friend inline bool operator<(weak_count const & a, weak_count const & b)
385 return std::less<counted_base *>()(a.pi_, b.pi_);
389 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
394 } // namespace detail
398 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED