1 #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED 2 #define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED 3 4 #ifndef BOOST_CONFIG_HPP 5 # include <boost/config.hpp> 6 #endif 7 # 8 #if defined(BOOST_HAS_PRAGMA_ONCE) 9 # pragma once 10 #endif 11 12 // 13 // This file is the adaptation for shared memory memory mapped 14 // files of boost/detail/sp_counted_impl.hpp 15 // 16 // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. 17 // Copyright 2004-2005 Peter Dimov 18 // Copyright 2006 Ion Gaztanaga 19 // 20 // Distributed under the Boost Software License, Version 1.0. (See 21 // accompanying file LICENSE_1_0.txt or copy at 22 // http://www.boost.org/LICENSE_1_0.txt) 23 // 24 25 #include <boost/interprocess/detail/config_begin.hpp> 26 #include <boost/interprocess/detail/workaround.hpp> 27 28 #include <boost/interprocess/containers/version_type.hpp> 29 #include <boost/interprocess/smart_ptr/detail/sp_counted_base.hpp> 30 #include <boost/interprocess/smart_ptr/scoped_ptr.hpp> 31 #include <boost/interprocess/detail/utilities.hpp> 32 #include <boost/container/allocator_traits.hpp> 33 #include <boost/intrusive/pointer_traits.hpp> 34 35 namespace boost { 36 37 namespace interprocess { 38 39 namespace ipcdetail { 40 41 //!A deleter for scoped_ptr that deallocates the memory 42 //!allocated for an object using a STL allocator. 43 template <class Allocator> 44 struct scoped_ptr_dealloc_functor 45 { 46 typedef typename Allocator::pointer pointer; 47 typedef ipcdetail::integral_constant<unsigned, 48 boost::interprocess::version<Allocator>::value> alloc_version; 49 typedef ipcdetail::integral_constant<unsigned, 1> allocator_v1; 50 typedef ipcdetail::integral_constant<unsigned, 2> allocator_v2; 51 52 private: priv_deallocateboost::interprocess::ipcdetail::scoped_ptr_dealloc_functor53 void priv_deallocate(const typename Allocator::pointer &p, allocator_v1) 54 { m_alloc.deallocate(p, 1); } 55 priv_deallocateboost::interprocess::ipcdetail::scoped_ptr_dealloc_functor56 void priv_deallocate(const typename Allocator::pointer &p, allocator_v2) 57 { m_alloc.deallocate_one(p); } 58 59 public: 60 Allocator& m_alloc; 61 scoped_ptr_dealloc_functorboost::interprocess::ipcdetail::scoped_ptr_dealloc_functor62 scoped_ptr_dealloc_functor(Allocator& a) 63 : m_alloc(a) {} 64 operator ()boost::interprocess::ipcdetail::scoped_ptr_dealloc_functor65 void operator()(pointer ptr) 66 { if (ptr) priv_deallocate(ptr, alloc_version()); } 67 }; 68 69 70 71 template<class A, class D> 72 class sp_counted_impl_pd 73 : public sp_counted_base 74 , boost::container::allocator_traits<A>::template 75 portable_rebind_alloc< sp_counted_impl_pd<A, D> >::type 76 , D // copy constructor must not throw 77 { 78 private: 79 typedef sp_counted_impl_pd<A, D> this_type; 80 typedef typename boost::container:: 81 allocator_traits<A>::template 82 portable_rebind_alloc 83 < this_type >::type this_allocator; 84 typedef typename boost::container:: 85 allocator_traits<A>::template 86 portable_rebind_alloc 87 < const this_type >::type const_this_allocator; 88 typedef typename this_allocator::pointer this_pointer; 89 typedef typename boost::intrusive:: 90 pointer_traits<this_pointer> this_pointer_traits; 91 92 sp_counted_impl_pd( sp_counted_impl_pd const & ); 93 sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); 94 95 typedef typename boost::intrusive:: 96 pointer_traits<typename A::pointer>::template 97 rebind_pointer<const D>::type const_deleter_pointer; 98 typedef typename boost::intrusive:: 99 pointer_traits<typename A::pointer>::template 100 rebind_pointer<const A>::type const_allocator_pointer; 101 102 typedef typename D::pointer pointer; 103 pointer m_ptr; 104 105 public: 106 // pre: d(p) must not throw 107 template<class Ptr> sp_counted_impl_pd(const Ptr & p,const A & a,const D & d)108 sp_counted_impl_pd(const Ptr & p, const A &a, const D &d ) 109 : this_allocator(a), D(d), m_ptr(p) 110 {} 111 get_deleter() const112 const_deleter_pointer get_deleter() const 113 { return const_deleter_pointer(&static_cast<const D&>(*this)); } 114 get_allocator() const115 const_allocator_pointer get_allocator() const 116 { return const_allocator_pointer(&static_cast<const A&>(*this)); } 117 dispose()118 void dispose() // nothrow 119 { static_cast<D&>(*this)(m_ptr); } 120 destroy()121 void destroy() // nothrow 122 { 123 //Self destruction, so move the allocator 124 this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this))); 125 BOOST_ASSERT(a_copy == *this); 126 this_pointer this_ptr(this_pointer_traits::pointer_to(*this)); 127 //Do it now! 128 scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> > 129 deleter_ptr(this_ptr, a_copy); 130 typedef typename this_allocator::value_type value_type; 131 ipcdetail::to_raw_pointer(this_ptr)->~value_type(); 132 } 133 release()134 void release() // nothrow 135 { 136 if(this->ref_release()){ 137 this->dispose(); 138 this->weak_release(); 139 } 140 } 141 weak_release()142 void weak_release() // nothrow 143 { 144 if(sp_counted_base::weak_release()){ 145 this->destroy(); 146 } 147 } 148 }; 149 150 151 } // namespace ipcdetail 152 153 } // namespace interprocess 154 155 } // namespace boost 156 157 #include <boost/interprocess/detail/config_end.hpp> 158 159 #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED 160