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
30 #include <exception> // for std::exception
37 class use_count_is_zero: public std::exception
41 virtual char const * what() const throw()
43 return "use_count_is_zero";
52 typedef detail::lightweight_mutex mutex_type;
57 use_count_(0), weak_count_(0), self_deleter_(&self_delete)
61 // pre: initial_use_count <= initial_weak_count
63 explicit counted_base(long initial_use_count, long initial_weak_count):
64 use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
68 virtual ~counted_base() // nothrow
72 // dispose() is called when use_count_ drops to zero, to release
73 // the resources managed by *this.
75 // counted_base doesn't manage any resources except itself, and
76 // the default implementation is a no-op.
78 // dispose() is not pure virtual since weak_ptr instantiates a
79 // counted_base in its default constructor.
81 virtual void dispose() // nothrow
87 #ifdef BOOST_HAS_THREADS
88 mutex_type::scoped_lock lock(mtx_);
91 if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
93 if(use_count_ == 0 && weak_count_ != 0) assert(false);
99 void release() // nothrow
105 #ifdef BOOST_HAS_THREADS
106 mutex_type::scoped_lock lock(mtx_);
108 new_use_count = --use_count_;
109 new_weak_count = --weak_count_;
112 if(new_use_count == 0)
117 if(new_weak_count == 0)
119 // not a direct 'delete this', because the inlined
120 // release() may use a different heap manager
125 void weak_add_ref() // nothrow
127 #ifdef BOOST_HAS_THREADS
128 mutex_type::scoped_lock lock(mtx_);
133 void weak_release() // nothrow
138 #ifdef BOOST_HAS_THREADS
139 mutex_type::scoped_lock lock(mtx_);
141 new_weak_count = --weak_count_;
144 if(new_weak_count == 0)
150 long use_count() const // nothrow
152 #ifdef BOOST_HAS_THREADS
153 mutex_type::scoped_lock lock(mtx_);
160 counted_base(counted_base const &);
161 counted_base & operator= (counted_base const &);
163 static void self_delete(counted_base * p)
168 // inv: use_count_ <= weak_count_
172 #ifdef BOOST_HAS_THREADS
173 mutable mutex_type mtx_;
175 void (*self_deleter_) (counted_base *);
178 inline void intrusive_ptr_add_ref(counted_base * p)
183 inline void intrusive_ptr_release(counted_base * p)
191 template<class P, class D> class counted_base_impl: public counted_base
195 P ptr; // copy constructor must not throw
196 D del; // copy constructor must not throw
198 counted_base_impl(counted_base_impl const &);
199 counted_base_impl & operator= (counted_base_impl const &);
203 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
205 counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
206 counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
210 virtual void dispose() // nothrow
224 friend class weak_count;
226 template<class P, class D> shared_count(P, D, counted_base const *);
230 shared_count(): pi_(new counted_base(1, 1))
234 explicit shared_count(counted_base * pi): pi_(pi) // never throws
239 template<class P, class D> shared_count(P p, D d, void const * = 0): pi_(0)
245 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
256 template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
261 #ifndef BOOST_NO_AUTO_PTR
263 // auto_ptr<Y> is special cased to provide the strong guarantee
266 explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
273 ~shared_count() // nothrow
278 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
283 explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
285 shared_count & operator= (shared_count const & r) // nothrow
287 counted_base * tmp = r.pi_;
295 void swap(shared_count & r) // nothrow
297 counted_base * tmp = r.pi_;
302 long use_count() const // nothrow
304 return pi_->use_count();
307 bool unique() const // nothrow
309 return pi_->use_count() == 1;
312 friend inline bool operator==(shared_count const & a, shared_count const & b)
314 return a.pi_ == b.pi_;
317 friend inline bool operator<(shared_count const & a, shared_count const & b)
319 return std::less<counted_base *>()(a.pi_, b.pi_);
329 friend class shared_count;
333 weak_count(): pi_(new counted_base(0, 1)) // can throw
337 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
342 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
347 ~weak_count() // nothrow
352 weak_count & operator= (shared_count const & r) // nothrow
354 counted_base * tmp = r.pi_;
362 weak_count & operator= (weak_count const & r) // nothrow
364 counted_base * tmp = r.pi_;
372 void swap(weak_count & r) // nothrow
374 counted_base * tmp = r.pi_;
379 long use_count() const // nothrow
381 return pi_->use_count();
384 friend inline bool operator==(weak_count const & a, weak_count const & b)
386 return a.pi_ == b.pi_;
389 friend inline bool operator<(weak_count const & a, weak_count const & b)
391 return std::less<counted_base *>()(a.pi_, b.pi_);
395 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
400 } // namespace detail
404 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED