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
32 # pragma warn -8026 // Functions with excep. spec. are not expanded inline
33 # pragma warn -8027 // Functions containing try are not expanded inline
39 class use_count_is_zero: public std::exception
43 virtual char const * what() const throw()
45 return "use_count_is_zero";
53 typedef detail::lightweight_mutex mutex_type;
58 use_count_(0), weak_count_(0)
62 // pre: initial_use_count <= initial_weak_count
64 explicit counted_base(long initial_use_count, long initial_weak_count):
65 use_count_(initial_use_count), weak_count_(initial_weak_count)
69 virtual ~counted_base() // nothrow
73 // dispose() is called when use_count_ drops to zero, to release
74 // the resources managed by *this.
76 // counted_base doesn't manage any resources except itself, and
77 // the default implementation is a no-op.
79 // dispose() is not pure virtual since weak_ptr instantiates a
80 // counted_base in its default constructor.
82 virtual void dispose() // nothrow
86 // destruct() is called when weak_count_ drops to zero.
88 virtual void destruct() // nothrow
95 #ifdef BOOST_HAS_THREADS
96 mutex_type::scoped_lock lock(mtx_);
98 #ifndef BOOST_NO_EXCEPTIONS
99 if(use_count_ == 0 && weak_count_ != 0) throw use_count_is_zero();
101 BOOST_NOEH_ASSERT(!(use_count_ == 0 && weak_count_ != 0));
106 void release() // nothrow
112 #ifdef BOOST_HAS_THREADS
113 mutex_type::scoped_lock lock(mtx_);
115 new_use_count = --use_count_;
116 new_weak_count = --weak_count_;
119 if(new_use_count == 0)
124 if(new_weak_count == 0)
130 void weak_add_ref() // nothrow
132 #ifdef BOOST_HAS_THREADS
133 mutex_type::scoped_lock lock(mtx_);
138 void weak_release() // nothrow
143 #ifdef BOOST_HAS_THREADS
144 mutex_type::scoped_lock lock(mtx_);
146 new_weak_count = --weak_count_;
149 if(new_weak_count == 0)
155 long use_count() const // nothrow
157 #ifdef BOOST_HAS_THREADS
158 mutex_type::scoped_lock lock(mtx_);
165 counted_base(counted_base const &);
166 counted_base & operator= (counted_base const &);
168 // inv: use_count_ <= weak_count_
173 #ifdef BOOST_HAS_THREADS
174 mutable mutex_type mtx_;
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)
241 #ifndef BOOST_NO_EXCEPTIONS
244 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
252 pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
253 BOOST_NOEH_ASSERT(pi_);
257 template<class P, class D> shared_count(P, D, counted_base * pi): pi_(pi)
262 #ifndef BOOST_NO_AUTO_PTR
264 // auto_ptr<Y> is special cased to provide the strong guarantee
267 explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
274 ~shared_count() // nothrow
279 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
284 explicit shared_count(weak_count const & r); // throws use_count_is_zero when r.use_count() == 0
286 shared_count & operator= (shared_count const & r) // nothrow
288 counted_base * tmp = r.pi_;
296 void swap(shared_count & r) // nothrow
298 counted_base * tmp = r.pi_;
303 long use_count() const // nothrow
305 return pi_->use_count();
308 bool unique() const // nothrow
310 return pi_->use_count() == 1;
313 friend inline bool operator==(shared_count const & a, shared_count const & b)
315 return a.pi_ == b.pi_;
318 friend inline bool operator<(shared_count const & a, shared_count const & b)
320 return std::less<counted_base *>()(a.pi_, b.pi_);
330 friend class shared_count;
334 weak_count(): pi_(new counted_base(0, 1)) // can throw
338 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
343 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
348 ~weak_count() // nothrow
353 weak_count & operator= (shared_count const & r) // nothrow
355 counted_base * tmp = r.pi_;
363 weak_count & operator= (weak_count const & r) // nothrow
365 counted_base * tmp = r.pi_;
373 void swap(weak_count & r) // nothrow
375 counted_base * tmp = r.pi_;
380 long use_count() const // nothrow
382 return pi_->use_count();
385 friend inline bool operator==(weak_count const & a, weak_count const & b)
387 return a.pi_ == b.pi_;
390 friend inline bool operator<(weak_count const & a, weak_count const & b)
392 return std::less<counted_base *>()(a.pi_, b.pi_);
396 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
401 } // namespace detail
406 # pragma warn .8027 // Functions containing try are not expanded inline
407 # pragma warn .8026 // Functions with excep. spec. are not expanded inline
410 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED