• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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