fix doc example typo
[boost.git] / boost / serialization / detail / shared_count_132.hpp
blob0665e8749d7e896c9d05a3da9f5dfe8a1911635a
1 #ifndef BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
2 #define BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
4 // MS compatible compilers support #pragma once
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
11 // detail/shared_count.hpp
13 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
15 // Distributed under the Boost Software License, Version 1.0. (See
16 // accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
20 #include <boost/config.hpp>
22 #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
23 # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
24 #endif
26 #include <boost/checked_delete.hpp>
27 #include <boost/serialization/throw_exception.hpp>
28 #include <boost/detail/lightweight_mutex.hpp>
30 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
31 #include <boost/detail/quick_allocator.hpp>
32 #endif
34 #include <memory> // std::auto_ptr, std::allocator
35 #include <functional> // std::less
36 #include <exception> // std::exception
37 #include <new> // std::bad_alloc
38 #include <typeinfo> // std::type_info in get_deleter
39 #include <cstddef> // std::size_t
41 #include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
42 #if defined(BOOST_NO_STDC_NAMESPACE)
43 namespace std{
44 using ::size_t;
45 } // namespace std
46 #endif
48 #ifdef __BORLANDC__
49 # pragma warn -8026 // Functions with excep. spec. are not expanded inline
50 # pragma warn -8027 // Functions containing try are not expanded inline
51 #endif
53 namespace boost_132 {
55 // Debug hooks
57 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
59 void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
60 void sp_array_constructor_hook(void * px);
61 void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
62 void sp_array_destructor_hook(void * px);
64 #endif
67 // The standard library that comes with Borland C++ 5.5.1
68 // defines std::exception and its members as having C calling
69 // convention (-pc). When the definition of bad_weak_ptr
70 // is compiled with -ps, the compiler issues an error.
71 // Hence, the temporary #pragma option -pc below. The version
72 // check is deliberately conservative.
74 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
75 # pragma option push -pc
76 #endif
78 class bad_weak_ptr: public std::exception
80 public:
82 virtual char const * what() const throw()
84 return "boost::bad_weak_ptr";
88 #if defined(__BORLANDC__) && __BORLANDC__ == 0x551
89 # pragma option pop
90 #endif
92 namespace detail{
94 class sp_counted_base
96 //private:
98 typedef boost::detail::lightweight_mutex mutex_type;
100 public:
102 sp_counted_base(): use_count_(1), weak_count_(1)
106 virtual ~sp_counted_base() // nothrow
110 // dispose() is called when use_count_ drops to zero, to release
111 // the resources managed by *this.
113 virtual void dispose() = 0; // nothrow
115 // destruct() is called when weak_count_ drops to zero.
117 virtual void destruct() // nothrow
119 delete this;
122 virtual void * get_deleter(std::type_info const & ti) = 0;
124 void add_ref_copy()
126 #if defined(BOOST_HAS_THREADS)
127 mutex_type::scoped_lock lock(mtx_);
128 #endif
129 ++use_count_;
132 void add_ref_lock()
134 #if defined(BOOST_HAS_THREADS)
135 mutex_type::scoped_lock lock(mtx_);
136 #endif
137 if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
138 ++use_count_;
141 void release() // nothrow
144 #if defined(BOOST_HAS_THREADS)
145 mutex_type::scoped_lock lock(mtx_);
146 #endif
147 long new_use_count = --use_count_;
149 if(new_use_count != 0) return;
152 dispose();
153 weak_release();
156 void weak_add_ref() // nothrow
158 #if defined(BOOST_HAS_THREADS)
159 mutex_type::scoped_lock lock(mtx_);
160 #endif
161 ++weak_count_;
164 void weak_release() // nothrow
166 long new_weak_count;
169 #if defined(BOOST_HAS_THREADS)
170 mutex_type::scoped_lock lock(mtx_);
171 #endif
172 new_weak_count = --weak_count_;
175 if(new_weak_count == 0)
177 destruct();
181 long use_count() const // nothrow
183 #if defined(BOOST_HAS_THREADS)
184 mutex_type::scoped_lock lock(mtx_);
185 #endif
186 return use_count_;
189 //private:
190 public:
191 sp_counted_base(sp_counted_base const &);
192 sp_counted_base & operator= (sp_counted_base const &);
194 long use_count_; // #shared
195 long weak_count_; // #weak + (#shared != 0)
197 #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
198 mutable mutex_type mtx_;
199 #endif
202 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
204 template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
206 boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
209 template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
211 boost::sp_array_constructor_hook(px);
214 template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
218 template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter<T> const &, int)
220 boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
223 template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter<T> const &, int)
225 boost::sp_array_destructor_hook(px);
228 template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
232 #endif
235 // Borland's Codeguard trips up over the -Vx- option here:
237 #ifdef __CODEGUARD__
238 # pragma option push -Vx-
239 #endif
241 template<class P, class D> class sp_counted_base_impl: public sp_counted_base
243 //private:
244 public:
245 P ptr; // copy constructor must not throw
246 D del; // copy constructor must not throw
248 sp_counted_base_impl(sp_counted_base_impl const &);
249 sp_counted_base_impl & operator= (sp_counted_base_impl const &);
251 typedef sp_counted_base_impl<P, D> this_type;
253 public:
255 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
257 sp_counted_base_impl(P p, D d): ptr(p), del(d)
259 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
260 detail::cbi_call_constructor_hook(this, p, d, 0);
261 #endif
264 virtual void dispose() // nothrow
266 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
267 detail::cbi_call_destructor_hook(this, ptr, del, 0);
268 #endif
269 del(ptr);
272 virtual void * get_deleter(std::type_info const & ti)
274 return ti == typeid(D)? &del: 0;
277 #if defined(BOOST_SP_USE_STD_ALLOCATOR)
279 void * operator new(std::size_t)
281 return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
284 void operator delete(void * p)
286 std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
289 #endif
291 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
293 void * operator new(std::size_t)
295 return boost::detail::quick_allocator<this_type>::alloc();
298 void operator delete(void * p)
300 boost::detail::quick_allocator<this_type>::dealloc(p);
303 #endif
306 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
308 int const shared_count_id = 0x2C35F101;
309 int const weak_count_id = 0x298C38A4;
311 #endif
313 class weak_count;
315 class shared_count
317 //private:
318 public:
319 sp_counted_base * pi_;
321 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
322 int id_;
323 #endif
325 friend class weak_count;
327 public:
329 shared_count(): pi_(0) // nothrow
330 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
331 , id_(shared_count_id)
332 #endif
336 template<class P, class D> shared_count(P p, D d): pi_(0)
337 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
338 , id_(shared_count_id)
339 #endif
341 #ifndef BOOST_NO_EXCEPTIONS
345 pi_ = new sp_counted_base_impl<P, D>(p, d);
347 catch(...)
349 d(p); // delete p
350 throw;
353 #else
355 pi_ = new sp_counted_base_impl<P, D>(p, d);
357 if(pi_ == 0)
359 d(p); // delete p
360 boost::serialization::throw_exception(std::bad_alloc());
363 #endif
366 #ifndef BOOST_NO_AUTO_PTR
368 // auto_ptr<Y> is special cased to provide the strong guarantee
370 template<class Y>
371 explicit shared_count(std::auto_ptr<Y> & r): pi_(
372 new sp_counted_base_impl<
373 Y *,
374 boost::checked_deleter<Y>
375 >(r.get(), boost::checked_deleter<Y>()))
376 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
377 , id_(shared_count_id)
378 #endif
380 r.release();
383 #endif
385 ~shared_count() // nothrow
387 if(pi_ != 0) pi_->release();
388 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
389 id_ = 0;
390 #endif
393 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
394 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
395 , id_(shared_count_id)
396 #endif
398 if(pi_ != 0) pi_->add_ref_copy();
401 explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
403 shared_count & operator= (shared_count const & r) // nothrow
405 sp_counted_base * tmp = r.pi_;
407 if(tmp != pi_)
409 if(tmp != 0) tmp->add_ref_copy();
410 if(pi_ != 0) pi_->release();
411 pi_ = tmp;
414 return *this;
417 void swap(shared_count & r) // nothrow
419 sp_counted_base * tmp = r.pi_;
420 r.pi_ = pi_;
421 pi_ = tmp;
424 long use_count() const // nothrow
426 return pi_ != 0? pi_->use_count(): 0;
429 bool unique() const // nothrow
431 return use_count() == 1;
434 friend inline bool operator==(shared_count const & a, shared_count const & b)
436 return a.pi_ == b.pi_;
439 friend inline bool operator<(shared_count const & a, shared_count const & b)
441 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
444 void * get_deleter(std::type_info const & ti) const
446 return pi_? pi_->get_deleter(ti): 0;
450 #ifdef __CODEGUARD__
451 # pragma option pop
452 #endif
455 class weak_count
457 private:
459 sp_counted_base * pi_;
461 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
462 int id_;
463 #endif
465 friend class shared_count;
467 public:
469 weak_count(): pi_(0) // nothrow
470 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
471 , id_(weak_count_id)
472 #endif
476 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
477 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
478 , id_(shared_count_id)
479 #endif
481 if(pi_ != 0) pi_->weak_add_ref();
484 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
485 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
486 , id_(shared_count_id)
487 #endif
489 if(pi_ != 0) pi_->weak_add_ref();
492 ~weak_count() // nothrow
494 if(pi_ != 0) pi_->weak_release();
495 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
496 id_ = 0;
497 #endif
500 weak_count & operator= (shared_count const & r) // nothrow
502 sp_counted_base * tmp = r.pi_;
503 if(tmp != 0) tmp->weak_add_ref();
504 if(pi_ != 0) pi_->weak_release();
505 pi_ = tmp;
507 return *this;
510 weak_count & operator= (weak_count const & r) // nothrow
512 sp_counted_base * tmp = r.pi_;
513 if(tmp != 0) tmp->weak_add_ref();
514 if(pi_ != 0) pi_->weak_release();
515 pi_ = tmp;
517 return *this;
520 void swap(weak_count & r) // nothrow
522 sp_counted_base * tmp = r.pi_;
523 r.pi_ = pi_;
524 pi_ = tmp;
527 long use_count() const // nothrow
529 return pi_ != 0? pi_->use_count(): 0;
532 friend inline bool operator==(weak_count const & a, weak_count const & b)
534 return a.pi_ == b.pi_;
537 friend inline bool operator<(weak_count const & a, weak_count const & b)
539 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
543 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
544 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
545 , id_(shared_count_id)
546 #endif
548 if(pi_ != 0)
550 pi_->add_ref_lock();
552 else
554 boost::serialization::throw_exception(bad_weak_ptr());
558 } // namespace detail
560 } // namespace boost
562 BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
564 #ifdef __BORLANDC__
565 # pragma warn .8027 // Functions containing try are not expanded inline
566 # pragma warn .8026 // Functions with excep. spec. are not expanded inline
567 #endif
569 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED