diff options
Diffstat (limited to 'boost/interprocess/smart_ptr/detail/shared_count.hpp')
-rw-r--r-- | boost/interprocess/smart_ptr/detail/shared_count.hpp | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/boost/interprocess/smart_ptr/detail/shared_count.hpp b/boost/interprocess/smart_ptr/detail/shared_count.hpp new file mode 100644 index 0000000000..0150ef6c00 --- /dev/null +++ b/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -0,0 +1,338 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/detail/shared_count.hpp +// +// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 +// (C) Copyright Peter Dimov 2004-2005 +// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> + +#include <boost/checked_delete.hpp> +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp> +#include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp> +#include <boost/interprocess/detail/utilities.hpp> +#include <boost/container/allocator/allocator_traits.hpp> +#include <boost/detail/no_exceptions_support.hpp> +#include <functional> // std::less + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +template<class T, class VoidAllocator, class Deleter> +class weak_count; + +template<class T, class VoidAllocator, class Deleter> +class shared_count +{ + public: + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<T>::type pointer; + + private: + typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl; + + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<counted_impl>::type counted_impl_ptr; + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<sp_counted_base>::type counted_base_ptr; + + typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits; + + typedef typename vallocator_traits::template + portable_rebind_alloc<counted_impl>::type counted_impl_allocator; + + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<const Deleter>::type const_deleter_pointer; + + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<const VoidAllocator>::type const_allocator_pointer; + + pointer m_px; + counted_impl_ptr m_pi; + + template <class T2, class VoidAllocator2, class Deleter2> + friend class weak_count; + + template <class T2, class VoidAllocator2, class Deleter2> + friend class shared_count; + + public: + + shared_count() + : m_px(0), m_pi(0) // nothrow + {} + + template <class Ptr> + shared_count(const shared_count &other_shared_count, const Ptr &p) + : m_px(p), m_pi(other_shared_count.m_pi) + {} + + template <class Ptr> + shared_count(const Ptr &p, const VoidAllocator &a, Deleter d) + : m_px(p), m_pi(0) + { + BOOST_TRY{ + if(p){ + counted_impl_allocator alloc(a); + m_pi = alloc.allocate(1); + //Anti-exception deallocator + scoped_ptr<counted_impl, + scoped_ptr_dealloc_functor<counted_impl_allocator> > + deallocator(m_pi, alloc); + //It's more correct to use VoidAllocator::construct but + //this needs copy constructor and we don't like it + new(ipcdetail::to_raw_pointer(m_pi))counted_impl(p, a, d); + deallocator.release(); + } + } + BOOST_CATCH (...){ + d(p); // delete p + BOOST_RETHROW + } + BOOST_CATCH_END + } + + ~shared_count() // nothrow + { + if(m_pi) + m_pi->release(); + } + + shared_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template<class Y> + explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template<class Y> + explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r) + : m_px(ptr), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + +/* + explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + boost::throw_exception( boost::interprocess::bad_weak_ptr() ); + } + } +*/ + template<class Y> + explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_px(r.m_px), m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + throw( boost::interprocess::bad_weak_ptr() ); + } + } + + const pointer &to_raw_pointer() const + { return m_px; } + + pointer &to_raw_pointer() + { return m_px; } + + shared_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + template<class Y> + shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + void swap(shared_count & r) // nothrow + { ipcdetail::do_swap(m_px, r.m_px); ipcdetail::do_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count(): 0; } + + bool unique() const // nothrow + { return use_count() == 1; } + + const_deleter_pointer get_deleter() const + { return m_pi ? m_pi->get_deleter() : 0; } + +// const_allocator_pointer get_allocator() const +// { return m_pi ? m_pi->get_allocator() : 0; } + + template<class T2, class VoidAllocator2, class Deleter2> + bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const + { return this->m_pi == other.m_pi; } + + template<class T2, class VoidAllocator2, class Deleter2> + bool internal_less (shared_count<T2, VoidAllocator2, Deleter2> const & other) const + { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); } +}; + +template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline +bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b) +{ return a.internal_equal(b); } + +template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline +bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b) +{ return a.internal_less(b); } + + +template<class T, class VoidAllocator, class Deleter> +class weak_count +{ + public: + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<T>::type pointer; + + private: + + typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl; + + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<counted_impl>::type counted_impl_ptr; + typedef typename boost::intrusive:: + pointer_traits<typename VoidAllocator::pointer>::template + rebind_pointer<sp_counted_base>::type counted_base_ptr; + + pointer m_px; + counted_impl_ptr m_pi; + + template <class T2, class VoidAllocator2, class Deleter2> + friend class weak_count; + + template <class T2, class VoidAllocator2, class Deleter2> + friend class shared_count; + + public: + + weak_count(): m_px(0), m_pi(0) // nothrow + {} + + template <class Y> + explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + weak_count(weak_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + template<class Y> + weak_count(weak_count<Y, VoidAllocator, Deleter> const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + ~weak_count() // nothrow + { if(m_pi != 0) m_pi->weak_release(); } + + template<class Y> + weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void set_pointer(const pointer &ptr) + { m_px = ptr; } + + template<class Y> + weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow + { + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void swap(weak_count & r) // nothrow + { ipcdetail::do_swap(m_px, r.m_px); ipcdetail::do_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count() : 0; } + + template<class T2, class VoidAllocator2, class Deleter2> + bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const + { return this->m_pi == other.m_pi; } + + template<class T2, class VoidAllocator2, class Deleter2> + bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const + { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); } +}; + +template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline +bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b) +{ return a.internal_equal(b); } + +template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline +bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b) +{ return a.internal_less(b); } + +} // namespace ipcdetail +} // namespace interprocess +} // namespace boost + + +#include <boost/interprocess/detail/config_end.hpp> + + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED |