Project revived from Feb2017
[EroSomnia.git] / deps / boost_1_63_0 / boost / serialization / detail / shared_count_132.hpp
bloba5872557cf2c7cf9df68d5a3985e8ee62ea35430
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)
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 namespace boost_132 {
50 // Debug hooks
52 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
54 void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
55 void sp_array_constructor_hook(void * px);
56 void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
57 void sp_array_destructor_hook(void * px);
59 #endif
62 // The standard library that comes with Borland C++ 5.5.1
63 // defines std::exception and its members as having C calling
64 // convention (-pc). When the definition of bad_weak_ptr
65 // is compiled with -ps, the compiler issues an error.
66 // Hence, the temporary #pragma option -pc below. The version
67 // check is deliberately conservative.
69 class bad_weak_ptr: public std::exception
71 public:
73 virtual char const * what() const throw()
75 return "boost::bad_weak_ptr";
79 namespace detail{
81 class sp_counted_base
83 //private:
85 typedef boost::detail::lightweight_mutex mutex_type;
87 public:
89 sp_counted_base(): use_count_(1), weak_count_(1)
93 virtual ~sp_counted_base() // nothrow
97 // dispose() is called when use_count_ drops to zero, to release
98 // the resources managed by *this.
100 virtual void dispose() = 0; // nothrow
102 // destruct() is called when weak_count_ drops to zero.
104 virtual void destruct() // nothrow
106 delete this;
109 virtual void * get_deleter(std::type_info const & ti) = 0;
111 void add_ref_copy()
113 #if defined(BOOST_HAS_THREADS)
114 mutex_type::scoped_lock lock(mtx_);
115 #endif
116 ++use_count_;
119 void add_ref_lock()
121 #if defined(BOOST_HAS_THREADS)
122 mutex_type::scoped_lock lock(mtx_);
123 #endif
124 if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
125 ++use_count_;
128 void release() // nothrow
131 #if defined(BOOST_HAS_THREADS)
132 mutex_type::scoped_lock lock(mtx_);
133 #endif
134 long new_use_count = --use_count_;
136 if(new_use_count != 0) return;
139 dispose();
140 weak_release();
143 void weak_add_ref() // nothrow
145 #if defined(BOOST_HAS_THREADS)
146 mutex_type::scoped_lock lock(mtx_);
147 #endif
148 ++weak_count_;
151 void weak_release() // nothrow
153 long new_weak_count;
156 #if defined(BOOST_HAS_THREADS)
157 mutex_type::scoped_lock lock(mtx_);
158 #endif
159 new_weak_count = --weak_count_;
162 if(new_weak_count == 0)
164 destruct();
168 long use_count() const // nothrow
170 #if defined(BOOST_HAS_THREADS)
171 mutex_type::scoped_lock lock(mtx_);
172 #endif
173 return use_count_;
176 //private:
177 public:
178 sp_counted_base(sp_counted_base const &);
179 sp_counted_base & operator= (sp_counted_base const &);
181 long use_count_; // #shared
182 long weak_count_; // #weak + (#shared != 0)
184 #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
185 mutable mutex_type mtx_;
186 #endif
189 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
191 template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
193 boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
196 template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
198 boost::sp_array_constructor_hook(px);
201 template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
205 template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &)
207 boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
210 template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &)
212 boost::sp_array_destructor_hook(px);
215 template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
219 #endif
222 // Borland's Codeguard trips up over the -Vx- option here:
224 #ifdef __CODEGUARD__
225 # pragma option push -Vx-
226 #endif
228 template<class P, class D> class sp_counted_base_impl: public sp_counted_base
230 //private:
231 public:
232 P ptr; // copy constructor must not throw
233 D del; // copy constructor must not throw
235 sp_counted_base_impl(sp_counted_base_impl const &);
236 sp_counted_base_impl & operator= (sp_counted_base_impl const &);
238 typedef sp_counted_base_impl<P, D> this_type;
240 public:
242 // pre: initial_use_count <= initial_weak_count, d(p) must not throw
244 sp_counted_base_impl(P p, D d): ptr(p), del(d)
246 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
247 detail::cbi_call_constructor_hook(this, p, d, 0);
248 #endif
251 virtual void dispose() // nothrow
253 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
254 detail::cbi_call_destructor_hook(this, ptr, del, 0);
255 #endif
256 del(ptr);
259 virtual void * get_deleter(std::type_info const & ti)
261 return ti == typeid(D)? &del: 0;
264 #if defined(BOOST_SP_USE_STD_ALLOCATOR)
266 void * operator new(std::size_t)
268 return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
271 void operator delete(void * p)
273 std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
276 #endif
278 #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
280 void * operator new(std::size_t)
282 return boost::detail::quick_allocator<this_type>::alloc();
285 void operator delete(void * p)
287 boost::detail::quick_allocator<this_type>::dealloc(p);
290 #endif
293 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
295 int const shared_count_id = 0x2C35F101;
296 int const weak_count_id = 0x298C38A4;
298 #endif
300 class weak_count;
302 class shared_count
304 //private:
305 public:
306 sp_counted_base * pi_;
308 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
309 int id_;
310 #endif
312 friend class weak_count;
314 public:
316 shared_count(): pi_(0) // nothrow
317 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
318 , id_(shared_count_id)
319 #endif
323 template<class P, class D> shared_count(P p, D d): pi_(0)
324 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
325 , id_(shared_count_id)
326 #endif
328 #ifndef BOOST_NO_EXCEPTIONS
332 pi_ = new sp_counted_base_impl<P, D>(p, d);
334 catch(...)
336 d(p); // delete p
337 throw;
340 #else
342 pi_ = new sp_counted_base_impl<P, D>(p, d);
344 if(pi_ == 0)
346 d(p); // delete p
347 boost::serialization::throw_exception(std::bad_alloc());
350 #endif
353 #ifndef BOOST_NO_AUTO_PTR
355 // auto_ptr<Y> is special cased to provide the strong guarantee
357 template<class Y>
358 explicit shared_count(std::auto_ptr<Y> & r): pi_(
359 new sp_counted_base_impl<
360 Y *,
361 boost::checked_deleter<Y>
362 >(r.get(), boost::checked_deleter<Y>()))
363 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
364 , id_(shared_count_id)
365 #endif
367 r.release();
370 #endif
372 ~shared_count() // nothrow
374 if(pi_ != 0) pi_->release();
375 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
376 id_ = 0;
377 #endif
380 shared_count(shared_count const & r): pi_(r.pi_) // nothrow
381 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
382 , id_(shared_count_id)
383 #endif
385 if(pi_ != 0) pi_->add_ref_copy();
388 explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
390 shared_count & operator= (shared_count const & r) // nothrow
392 sp_counted_base * tmp = r.pi_;
394 if(tmp != pi_)
396 if(tmp != 0) tmp->add_ref_copy();
397 if(pi_ != 0) pi_->release();
398 pi_ = tmp;
401 return *this;
404 void swap(shared_count & r) // nothrow
406 sp_counted_base * tmp = r.pi_;
407 r.pi_ = pi_;
408 pi_ = tmp;
411 long use_count() const // nothrow
413 return pi_ != 0? pi_->use_count(): 0;
416 bool unique() const // nothrow
418 return use_count() == 1;
421 friend inline bool operator==(shared_count const & a, shared_count const & b)
423 return a.pi_ == b.pi_;
426 friend inline bool operator<(shared_count const & a, shared_count const & b)
428 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
431 void * get_deleter(std::type_info const & ti) const
433 return pi_? pi_->get_deleter(ti): 0;
437 #ifdef __CODEGUARD__
438 # pragma option pop
439 #endif
442 class weak_count
444 private:
446 sp_counted_base * pi_;
448 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
449 int id_;
450 #endif
452 friend class shared_count;
454 public:
456 weak_count(): pi_(0) // nothrow
457 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
458 , id_(weak_count_id)
459 #endif
463 weak_count(shared_count const & r): pi_(r.pi_) // nothrow
464 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
465 , id_(shared_count_id)
466 #endif
468 if(pi_ != 0) pi_->weak_add_ref();
471 weak_count(weak_count const & r): pi_(r.pi_) // nothrow
472 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
473 , id_(shared_count_id)
474 #endif
476 if(pi_ != 0) pi_->weak_add_ref();
479 ~weak_count() // nothrow
481 if(pi_ != 0) pi_->weak_release();
482 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
483 id_ = 0;
484 #endif
487 weak_count & operator= (shared_count const & r) // nothrow
489 sp_counted_base * tmp = r.pi_;
490 if(tmp != 0) tmp->weak_add_ref();
491 if(pi_ != 0) pi_->weak_release();
492 pi_ = tmp;
494 return *this;
497 weak_count & operator= (weak_count const & r) // nothrow
499 sp_counted_base * tmp = r.pi_;
500 if(tmp != 0) tmp->weak_add_ref();
501 if(pi_ != 0) pi_->weak_release();
502 pi_ = tmp;
504 return *this;
507 void swap(weak_count & r) // nothrow
509 sp_counted_base * tmp = r.pi_;
510 r.pi_ = pi_;
511 pi_ = tmp;
514 long use_count() const // nothrow
516 return pi_ != 0? pi_->use_count(): 0;
519 friend inline bool operator==(weak_count const & a, weak_count const & b)
521 return a.pi_ == b.pi_;
524 friend inline bool operator<(weak_count const & a, weak_count const & b)
526 return std::less<sp_counted_base *>()(a.pi_, b.pi_);
530 inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
531 #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
532 , id_(shared_count_id)
533 #endif
535 if(pi_ != 0)
537 pi_->add_ref_lock();
539 else
541 boost::serialization::throw_exception(bad_weak_ptr());
545 } // namespace detail
547 } // namespace boost
549 BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
551 #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED