Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp Chris@16: // Chris@16: // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 Chris@16: // (C) Copyright Peter Dimov 2004-2005 Chris@16: // (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED Chris@16: #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@101: #include Chris@101: #include //std::less Chris@101: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: namespace ipcdetail{ Chris@16: Chris@16: template Chris@16: class weak_count; Chris@16: Chris@16: template Chris@16: class shared_count Chris@16: { Chris@16: public: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type pointer; Chris@16: Chris@16: private: Chris@16: typedef sp_counted_impl_pd counted_impl; Chris@16: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type counted_impl_ptr; Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type counted_base_ptr; Chris@16: Chris@16: typedef boost::container::allocator_traits vallocator_traits; Chris@16: Chris@16: typedef typename vallocator_traits::template Chris@16: portable_rebind_alloc::type counted_impl_allocator; Chris@16: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type const_deleter_pointer; Chris@16: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type const_allocator_pointer; Chris@16: Chris@16: pointer m_px; Chris@16: counted_impl_ptr m_pi; Chris@16: Chris@16: template Chris@16: friend class weak_count; Chris@16: Chris@16: template Chris@16: friend class shared_count; Chris@16: Chris@16: public: Chris@16: Chris@16: shared_count() Chris@16: : m_px(0), m_pi(0) // nothrow Chris@16: {} Chris@16: Chris@16: template Chris@16: shared_count(const shared_count &other_shared_count, const Ptr &p) Chris@16: : m_px(p), m_pi(other_shared_count.m_pi) Chris@16: {} Chris@16: Chris@16: template Chris@16: shared_count(const Ptr &p, const VoidAllocator &a, Deleter d) Chris@16: : m_px(p), m_pi(0) Chris@16: { Chris@16: BOOST_TRY{ Chris@16: if(p){ Chris@16: counted_impl_allocator alloc(a); Chris@16: m_pi = alloc.allocate(1); Chris@16: //Anti-exception deallocator Chris@16: scoped_ptr > Chris@16: deallocator(m_pi, alloc); Chris@16: //It's more correct to use VoidAllocator::construct but Chris@16: //this needs copy constructor and we don't like it Chris@101: ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d); Chris@16: deallocator.release(); Chris@16: } Chris@16: } Chris@16: BOOST_CATCH (...){ Chris@16: d(p); // delete p Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: Chris@16: ~shared_count() // nothrow Chris@16: { Chris@16: if(m_pi) Chris@16: m_pi->release(); Chris@16: } Chris@16: Chris@16: shared_count(shared_count const & r) Chris@16: : m_px(r.m_px), m_pi(r.m_pi) // nothrow Chris@16: { if( m_pi != 0 ) m_pi->add_ref_copy(); } Chris@16: Chris@16: //this is a test Chris@16: template Chris@16: explicit shared_count(shared_count const & r) Chris@16: : m_px(r.m_px), m_pi(r.m_pi) // nothrow Chris@16: { if( m_pi != 0 ) m_pi->add_ref_copy(); } Chris@16: Chris@16: //this is a test Chris@16: template Chris@16: explicit shared_count(const pointer & ptr, shared_count const & r) Chris@16: : m_px(ptr), m_pi(r.m_pi) // nothrow Chris@16: { if( m_pi != 0 ) m_pi->add_ref_copy(); } Chris@16: Chris@16: /* Chris@16: explicit shared_count(weak_count const & r) Chris@16: // throws bad_weak_ptr when r.use_count() == 0 Chris@16: : m_pi( r.m_pi ) Chris@16: { Chris@16: if( m_pi == 0 || !m_pi->add_ref_lock() ){ Chris@16: boost::throw_exception( boost::interprocess::bad_weak_ptr() ); Chris@16: } Chris@16: } Chris@16: */ Chris@16: template Chris@16: explicit shared_count(weak_count const & r) Chris@16: // throws bad_weak_ptr when r.use_count() == 0 Chris@16: : m_px(r.m_px), m_pi( r.m_pi ) Chris@16: { Chris@16: if( m_pi == 0 || !m_pi->add_ref_lock() ){ Chris@16: throw( boost::interprocess::bad_weak_ptr() ); Chris@16: } Chris@16: } Chris@16: Chris@16: const pointer &to_raw_pointer() const Chris@16: { return m_px; } Chris@16: Chris@16: pointer &to_raw_pointer() Chris@16: { return m_px; } Chris@16: Chris@16: shared_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: m_px = r.m_px; Chris@16: counted_impl_ptr tmp = r.m_pi; Chris@16: if( tmp != m_pi ){ Chris@16: if(tmp != 0) tmp->add_ref_copy(); Chris@16: if(m_pi != 0) m_pi->release(); Chris@16: m_pi = tmp; Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: shared_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: m_px = r.m_px; Chris@16: counted_impl_ptr tmp = r.m_pi; Chris@16: if( tmp != m_pi ){ Chris@16: if(tmp != 0) tmp->add_ref_copy(); Chris@16: if(m_pi != 0) m_pi->release(); Chris@16: m_pi = tmp; Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(shared_count & r) // nothrow Chris@101: { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { return m_pi != 0? m_pi->use_count(): 0; } Chris@16: Chris@16: bool unique() const // nothrow Chris@16: { return use_count() == 1; } Chris@16: Chris@16: const_deleter_pointer get_deleter() const Chris@16: { return m_pi ? m_pi->get_deleter() : 0; } Chris@16: Chris@16: // const_allocator_pointer get_allocator() const Chris@16: // { return m_pi ? m_pi->get_allocator() : 0; } Chris@16: Chris@16: template Chris@16: bool internal_equal (shared_count const & other) const Chris@16: { return this->m_pi == other.m_pi; } Chris@16: Chris@16: template Chris@16: bool internal_less (shared_count const & other) const Chris@16: { return std::less()(this->m_pi, other.m_pi); } Chris@16: }; Chris@16: Chris@16: template inline Chris@16: bool operator==(shared_count const & a, shared_count const & b) Chris@16: { return a.internal_equal(b); } Chris@16: Chris@16: template inline Chris@16: bool operator<(shared_count const & a, shared_count const & b) Chris@16: { return a.internal_less(b); } Chris@16: Chris@16: Chris@16: template Chris@16: class weak_count Chris@16: { Chris@16: public: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type pointer; Chris@16: Chris@16: private: Chris@16: Chris@16: typedef sp_counted_impl_pd counted_impl; Chris@16: Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type counted_impl_ptr; Chris@16: typedef typename boost::intrusive:: Chris@16: pointer_traits::template Chris@16: rebind_pointer::type counted_base_ptr; Chris@16: Chris@16: pointer m_px; Chris@16: counted_impl_ptr m_pi; Chris@16: Chris@16: template Chris@16: friend class weak_count; Chris@16: Chris@16: template Chris@16: friend class shared_count; Chris@16: Chris@16: public: Chris@16: Chris@16: weak_count(): m_px(0), m_pi(0) // nothrow Chris@16: {} Chris@16: Chris@16: template Chris@16: explicit weak_count(shared_count const & r) Chris@16: : m_px(r.m_px), m_pi(r.m_pi) // nothrow Chris@16: { if(m_pi != 0) m_pi->weak_add_ref(); } Chris@16: Chris@16: weak_count(weak_count const & r) Chris@16: : m_px(r.m_px), m_pi(r.m_pi) // nothrow Chris@16: { if(m_pi != 0) m_pi->weak_add_ref(); } Chris@16: Chris@16: template Chris@16: weak_count(weak_count const & r) Chris@16: : m_px(r.m_px), m_pi(r.m_pi) // nothrow Chris@16: { if(m_pi != 0) m_pi->weak_add_ref(); } Chris@16: Chris@16: ~weak_count() // nothrow Chris@16: { if(m_pi != 0) m_pi->weak_release(); } Chris@16: Chris@16: template Chris@16: weak_count & operator= (shared_count const & r) // nothrow Chris@16: { Chris@16: m_px = r.m_px; Chris@16: counted_impl_ptr tmp = r.m_pi; Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(m_pi != 0) m_pi->weak_release(); Chris@16: m_pi = tmp; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: weak_count & operator= (weak_count const & r) // nothrow Chris@16: { Chris@16: m_px = r.m_px; Chris@16: counted_impl_ptr tmp = r.m_pi; Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(m_pi != 0) m_pi->weak_release(); Chris@16: m_pi = tmp; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void set_pointer(const pointer &ptr) Chris@16: { m_px = ptr; } Chris@16: Chris@16: template Chris@16: weak_count & operator= (weak_count const& r) // nothrow Chris@16: { Chris@16: counted_impl_ptr tmp = r.m_pi; Chris@16: if(tmp != 0) tmp->weak_add_ref(); Chris@16: if(m_pi != 0) m_pi->weak_release(); Chris@16: m_pi = tmp; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void swap(weak_count & r) // nothrow Chris@101: { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); } Chris@16: Chris@16: long use_count() const // nothrow Chris@16: { return m_pi != 0? m_pi->use_count() : 0; } Chris@16: Chris@16: template Chris@16: bool internal_equal (weak_count const & other) const Chris@16: { return this->m_pi == other.m_pi; } Chris@16: Chris@16: template Chris@16: bool internal_less (weak_count const & other) const Chris@16: { return std::less()(this->m_pi, other.m_pi); } Chris@16: }; Chris@16: Chris@16: template inline Chris@16: bool operator==(weak_count const & a, weak_count const & b) Chris@16: { return a.internal_equal(b); } Chris@16: Chris@16: template inline Chris@16: bool operator<(weak_count const & a, weak_count const & b) Chris@16: { return a.internal_less(b); } Chris@16: Chris@16: } // namespace ipcdetail Chris@16: } // namespace interprocess Chris@16: } // namespace boost Chris@16: Chris@16: Chris@16: #include Chris@16: Chris@16: Chris@16: #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED