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)
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.
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>
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)
49
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
50
# pragma warn -8027 // Functions containing try are not expanded inline
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);
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
78
class bad_weak_ptr: public std::exception
82
virtual char const * what() const throw()
84
return "boost::bad_weak_ptr";
88
#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
98
typedef boost::detail::lightweight_mutex mutex_type;
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
122
virtual void * get_deleter(std::type_info const & ti) = 0;
126
#if defined(BOOST_HAS_THREADS)
127
mutex_type::scoped_lock lock(mtx_);
134
#if defined(BOOST_HAS_THREADS)
135
mutex_type::scoped_lock lock(mtx_);
137
if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
141
void release() // nothrow
144
#if defined(BOOST_HAS_THREADS)
145
mutex_type::scoped_lock lock(mtx_);
147
long new_use_count = --use_count_;
149
if(new_use_count != 0) return;
156
void weak_add_ref() // nothrow
158
#if defined(BOOST_HAS_THREADS)
159
mutex_type::scoped_lock lock(mtx_);
164
void weak_release() // nothrow
169
#if defined(BOOST_HAS_THREADS)
170
mutex_type::scoped_lock lock(mtx_);
172
new_weak_count = --weak_count_;
175
if(new_weak_count == 0)
181
long use_count() const // nothrow
183
#if defined(BOOST_HAS_THREADS)
184
mutex_type::scoped_lock lock(mtx_);
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_;
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)
235
// Borland's Codeguard trips up over the -Vx- option here:
238
# pragma option push -Vx-
241
template<class P, class D> class sp_counted_base_impl: public sp_counted_base
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;
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);
264
virtual void dispose() // nothrow
266
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
267
detail::cbi_call_destructor_hook(this, ptr, del, 0);
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);
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);
306
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
308
int const shared_count_id = 0x2C35F101;
309
int const weak_count_id = 0x298C38A4;
319
sp_counted_base * pi_;
321
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
325
friend class weak_count;
329
shared_count(): pi_(0) // nothrow
330
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
331
, id_(shared_count_id)
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)
341
#ifndef BOOST_NO_EXCEPTIONS
345
pi_ = new sp_counted_base_impl<P, D>(p, d);
355
pi_ = new sp_counted_base_impl<P, D>(p, d);
360
boost::serialization::throw_exception(std::bad_alloc());
366
#ifndef BOOST_NO_AUTO_PTR
368
// auto_ptr<Y> is special cased to provide the strong guarantee
371
explicit shared_count(std::auto_ptr<Y> & r): pi_(
372
new sp_counted_base_impl<
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)
385
~shared_count() // nothrow
387
if(pi_ != 0) pi_->release();
388
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
393
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
394
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
395
, id_(shared_count_id)
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_;
409
if(tmp != 0) tmp->add_ref_copy();
410
if(pi_ != 0) pi_->release();
417
void swap(shared_count & r) // nothrow
419
sp_counted_base * tmp = r.pi_;
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;
459
sp_counted_base * pi_;
461
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
465
friend class shared_count;
469
weak_count(): pi_(0) // nothrow
470
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
476
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
477
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
478
, id_(shared_count_id)
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)
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)
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();
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();
520
void swap(weak_count & r) // nothrow
522
sp_counted_base * tmp = r.pi_;
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)
554
boost::serialization::throw_exception(bad_weak_ptr());
558
} // namespace detail
562
BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
565
# pragma warn .8027 // Functions containing try are not expanded inline
566
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
569
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED