Chris@16: #ifndef BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED Chris@16: #define BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: // Chris@16: // detail/shared_count.hpp Chris@16: // Chris@16: // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) Chris@16: # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #include // std::auto_ptr, std::allocator Chris@16: #include // std::less Chris@16: #include // std::exception Chris@16: #include // std::bad_alloc Chris@16: #include // std::type_info in get_deleter Chris@16: #include // std::size_t Chris@16: Chris@16: #include // msvc 6.0 needs this for warning suppression Chris@16: #if defined(BOOST_NO_STDC_NAMESPACE) Chris@16: namespace std{ Chris@16: using ::size_t; Chris@16: } // namespace std Chris@16: #endif Chris@16: Chris@16: #ifdef __BORLANDC__ Chris@16: # pragma warn -8026 // Functions with excep. spec. are not expanded inline Chris@16: # pragma warn -8027 // Functions containing try are not expanded inline Chris@16: #endif Chris@16: Chris@16: namespace boost_132 { Chris@16: Chris@16: // Debug hooks Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: Chris@16: void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn); Chris@16: void sp_array_constructor_hook(void * px); Chris@16: void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn); Chris@16: void sp_array_destructor_hook(void * px); Chris@16: Chris@16: #endif Chris@16: Chris@16: Chris@16: // The standard library that comes with Borland C++ 5.5.1 Chris@16: // defines std::exception and its members as having C calling Chris@16: // convention (-pc). When the definition of bad_weak_ptr Chris@16: // is compiled with -ps, the compiler issues an error. Chris@16: // Hence, the temporary #pragma option -pc below. The version Chris@16: // check is deliberately conservative. Chris@16: Chris@16: #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 Chris@16: # pragma option push -pc Chris@16: #endif Chris@16: Chris@16: class bad_weak_ptr: public std::exception Chris@16: { Chris@16: public: Chris@16: Chris@16: virtual char const * what() const throw() Chris@16: { Chris@16: return "boost::bad_weak_ptr"; Chris@16: } Chris@16: }; Chris@16: Chris@16: #if defined(__BORLANDC__) && __BORLANDC__ == 0x551 Chris@16: # pragma option pop Chris@16: #endif Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: class sp_counted_base Chris@16: { Chris@16: //private: Chris@16: Chris@16: typedef boost::detail::lightweight_mutex mutex_type; Chris@16: Chris@16: public: Chris@16: Chris@16: sp_counted_base(): use_count_(1), weak_count_(1) Chris@16: { Chris@16: } Chris@16: Chris@16: virtual ~sp_counted_base() // nothrow Chris@16: { Chris@16: } Chris@16: Chris@16: // dispose() is called when use_count_ drops to zero, to release Chris@16: // the resources managed by *this. Chris@16: Chris@16: virtual void dispose() = 0; // nothrow Chris@16: Chris@16: // destruct() is called when weak_count_ drops to zero. Chris@16: Chris@16: virtual void destruct() // nothrow Chris@16: { Chris@16: delete this; Chris@16: } Chris@16: Chris@16: virtual void * get_deleter(std::type_info const & ti) = 0; Chris@16: Chris@16: void add_ref_copy() Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: ++use_count_; Chris@16: } Chris@16: Chris@16: void add_ref_lock() Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr()); Chris@16: ++use_count_; Chris@16: } Chris@16: Chris@16: void release() // nothrow Chris@16: { Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: long new_use_count = --use_count_; Chris@16: Chris@16: if(new_use_count != 0) return; Chris@16: } Chris@16: Chris@16: dispose(); Chris@16: weak_release(); Chris@16: } Chris@16: Chris@16: void weak_add_ref() // nothrow Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: ++weak_count_; Chris@16: } Chris@16: Chris@16: void weak_release() // nothrow Chris@16: { Chris@16: long new_weak_count; Chris@16: Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: new_weak_count = --weak_count_; Chris@16: } Chris@16: Chris@16: if(new_weak_count == 0) Chris@16: { Chris@16: destruct(); Chris@16: } Chris@16: } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { Chris@16: #if defined(BOOST_HAS_THREADS) Chris@16: mutex_type::scoped_lock lock(mtx_); Chris@16: #endif Chris@16: return use_count_; Chris@16: } Chris@16: Chris@16: //private: Chris@16: public: Chris@16: sp_counted_base(sp_counted_base const &); Chris@16: sp_counted_base & operator= (sp_counted_base const &); Chris@16: Chris@16: long use_count_; // #shared Chris@16: long weak_count_; // #weak + (#shared != 0) Chris@16: Chris@16: #if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32) Chris@16: mutable mutex_type mtx_; Chris@16: #endif Chris@16: }; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: Chris@101: template void cbi_call_constructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &, int) Chris@16: { Chris@16: boost::sp_scalar_constructor_hook(px, sizeof(T), pn); Chris@16: } Chris@16: Chris@101: template void cbi_call_constructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &, int) Chris@16: { Chris@16: boost::sp_array_constructor_hook(px); Chris@16: } Chris@16: Chris@16: template void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long) Chris@16: { Chris@16: } Chris@16: Chris@101: template void cbi_call_destructor_hook(sp_counted_base * pn, T * px, boost::checked_deleter< T > const &, int) Chris@16: { Chris@16: boost::sp_scalar_destructor_hook(px, sizeof(T), pn); Chris@16: } Chris@16: Chris@101: template void cbi_call_destructor_hook(sp_counted_base *, T * px, boost::checked_array_deleter< T > const &, int) Chris@16: { Chris@16: boost::sp_array_destructor_hook(px); Chris@16: } Chris@16: Chris@16: template void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long) Chris@16: { Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: // Chris@16: // Borland's Codeguard trips up over the -Vx- option here: Chris@16: // Chris@16: #ifdef __CODEGUARD__ Chris@16: # pragma option push -Vx- Chris@16: #endif Chris@16: Chris@16: template class sp_counted_base_impl: public sp_counted_base Chris@16: { Chris@16: //private: Chris@16: public: Chris@16: P ptr; // copy constructor must not throw Chris@16: D del; // copy constructor must not throw Chris@16: Chris@16: sp_counted_base_impl(sp_counted_base_impl const &); Chris@16: sp_counted_base_impl & operator= (sp_counted_base_impl const &); Chris@16: Chris@16: typedef sp_counted_base_impl this_type; Chris@16: Chris@16: public: Chris@16: Chris@16: // pre: initial_use_count <= initial_weak_count, d(p) must not throw Chris@16: Chris@16: sp_counted_base_impl(P p, D d): ptr(p), del(d) Chris@16: { Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: detail::cbi_call_constructor_hook(this, p, d, 0); Chris@16: #endif Chris@16: } Chris@16: Chris@16: virtual void dispose() // nothrow Chris@16: { Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: detail::cbi_call_destructor_hook(this, ptr, del, 0); Chris@16: #endif Chris@16: del(ptr); Chris@16: } Chris@16: Chris@16: virtual void * get_deleter(std::type_info const & ti) Chris@16: { Chris@16: return ti == typeid(D)? &del: 0; Chris@16: } Chris@16: Chris@16: #if defined(BOOST_SP_USE_STD_ALLOCATOR) Chris@16: Chris@16: void * operator new(std::size_t) Chris@16: { Chris@16: return std::allocator().allocate(1, static_cast(0)); Chris@16: } Chris@16: Chris@16: void operator delete(void * p) Chris@16: { Chris@16: std::allocator().deallocate(static_cast(p), 1); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) Chris@16: Chris@16: void * operator new(std::size_t) Chris@16: { Chris@16: return boost::detail::quick_allocator::alloc(); Chris@16: } Chris@16: Chris@16: void operator delete(void * p) Chris@16: { Chris@16: boost::detail::quick_allocator::dealloc(p); Chris@16: } Chris@16: Chris@16: #endif Chris@16: }; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: Chris@16: int const shared_count_id = 0x2C35F101; Chris@16: int const weak_count_id = 0x298C38A4; Chris@16: Chris@16: #endif Chris@16: Chris@16: class weak_count; Chris@16: Chris@16: class shared_count Chris@16: { Chris@16: //private: Chris@16: public: Chris@16: sp_counted_base * pi_; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: int id_; Chris@16: #endif Chris@16: Chris@16: friend class weak_count; Chris@16: Chris@16: public: Chris@16: Chris@16: shared_count(): pi_(0) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: } Chris@16: Chris@16: template shared_count(P p, D d): pi_(0) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: #ifndef BOOST_NO_EXCEPTIONS Chris@16: Chris@16: try Chris@16: { Chris@16: pi_ = new sp_counted_base_impl(p, d); Chris@16: } Chris@16: catch(...) Chris@16: { Chris@16: d(p); // delete p Chris@16: throw; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: pi_ = new sp_counted_base_impl(p, d); Chris@16: Chris@16: if(pi_ == 0) Chris@16: { Chris@16: d(p); // delete p Chris@16: boost::serialization::throw_exception(std::bad_alloc()); Chris@16: } Chris@16: Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifndef BOOST_NO_AUTO_PTR Chris@16: Chris@16: // auto_ptr is special cased to provide the strong guarantee Chris@16: Chris@16: template Chris@16: explicit shared_count(std::auto_ptr & r): pi_( Chris@16: new sp_counted_base_impl< Chris@16: Y *, Chris@16: boost::checked_deleter Chris@16: >(r.get(), boost::checked_deleter())) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: r.release(); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: ~shared_count() // nothrow Chris@16: { Chris@16: if(pi_ != 0) pi_->release(); Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: id_ = 0; Chris@16: #endif Chris@16: } Chris@16: Chris@16: shared_count(shared_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) pi_->add_ref_copy(); Chris@16: } Chris@16: Chris@16: explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 Chris@16: Chris@16: shared_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: Chris@16: if(tmp != pi_) Chris@16: { Chris@16: if(tmp != 0) tmp->add_ref_copy(); Chris@16: if(pi_ != 0) pi_->release(); Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(shared_count & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: r.pi_ = pi_; Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { Chris@16: return pi_ != 0? pi_->use_count(): 0; Chris@16: } Chris@16: Chris@16: bool unique() const // nothrow Chris@16: { Chris@16: return use_count() == 1; Chris@16: } Chris@16: Chris@16: friend inline bool operator==(shared_count const & a, shared_count const & b) Chris@16: { Chris@16: return a.pi_ == b.pi_; Chris@16: } Chris@16: Chris@16: friend inline bool operator<(shared_count const & a, shared_count const & b) Chris@16: { Chris@16: return std::less()(a.pi_, b.pi_); Chris@16: } Chris@16: Chris@16: void * get_deleter(std::type_info const & ti) const Chris@16: { Chris@16: return pi_? pi_->get_deleter(ti): 0; Chris@16: } Chris@16: }; Chris@16: Chris@16: #ifdef __CODEGUARD__ Chris@16: # pragma option pop Chris@16: #endif Chris@16: Chris@16: Chris@16: class weak_count Chris@16: { Chris@16: private: Chris@16: Chris@16: sp_counted_base * pi_; Chris@16: Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: int id_; Chris@16: #endif Chris@16: Chris@16: friend class shared_count; Chris@16: Chris@16: public: Chris@16: Chris@16: weak_count(): pi_(0) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(weak_count_id) Chris@16: #endif Chris@16: { Chris@16: } Chris@16: Chris@16: weak_count(shared_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_add_ref(); Chris@16: } Chris@16: Chris@16: weak_count(weak_count const & r): pi_(r.pi_) // nothrow Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_add_ref(); Chris@16: } Chris@16: Chris@16: ~weak_count() // nothrow Chris@16: { Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: id_ = 0; Chris@16: #endif Chris@16: } Chris@16: Chris@16: weak_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: pi_ = tmp; Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: weak_count & operator= (weak_count const & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(pi_ != 0) pi_->weak_release(); Chris@16: pi_ = tmp; Chris@16: Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(weak_count & r) // nothrow Chris@16: { Chris@16: sp_counted_base * tmp = r.pi_; Chris@16: r.pi_ = pi_; Chris@16: pi_ = tmp; Chris@16: } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { Chris@16: return pi_ != 0? pi_->use_count(): 0; Chris@16: } Chris@16: Chris@16: friend inline bool operator==(weak_count const & a, weak_count const & b) Chris@16: { Chris@16: return a.pi_ == b.pi_; Chris@16: } Chris@16: Chris@16: friend inline bool operator<(weak_count const & a, weak_count const & b) Chris@16: { Chris@16: return std::less()(a.pi_, b.pi_); Chris@16: } Chris@16: }; Chris@16: Chris@16: inline shared_count::shared_count(weak_count const & r): pi_(r.pi_) Chris@16: #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) Chris@16: , id_(shared_count_id) Chris@16: #endif Chris@16: { Chris@16: if(pi_ != 0) Chris@16: { Chris@16: pi_->add_ref_lock(); Chris@16: } Chris@16: else Chris@16: { Chris@16: boost::serialization::throw_exception(bad_weak_ptr()); Chris@16: } Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base) Chris@16: Chris@16: #ifdef __BORLANDC__ Chris@16: # pragma warn .8027 // Functions containing try are not expanded inline Chris@16: # pragma warn .8026 // Functions with excep. spec. are not expanded inline Chris@16: #endif Chris@16: Chris@16: #endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED