]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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: | |
53 | void priv_deallocate(const typename Allocator::pointer &p, allocator_v1) | |
54 | { m_alloc.deallocate(p, 1); } | |
55 | ||
56 | void priv_deallocate(const typename Allocator::pointer &p, allocator_v2) | |
57 | { m_alloc.deallocate_one(p); } | |
58 | ||
59 | public: | |
60 | Allocator& m_alloc; | |
61 | ||
62 | scoped_ptr_dealloc_functor(Allocator& a) | |
63 | : m_alloc(a) {} | |
64 | ||
65 | 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> | |
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 | ||
112 | const_deleter_pointer get_deleter() const | |
113 | { return const_deleter_pointer(&static_cast<const D&>(*this)); } | |
114 | ||
115 | const_allocator_pointer get_allocator() const | |
116 | { return const_allocator_pointer(&static_cast<const A&>(*this)); } | |
117 | ||
118 | void dispose() // nothrow | |
119 | { static_cast<D&>(*this)(m_ptr); } | |
120 | ||
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 | ||
134 | void release() // nothrow | |
135 | { | |
136 | if(this->ref_release()){ | |
137 | this->dispose(); | |
138 | this->weak_release(); | |
139 | } | |
140 | } | |
141 | ||
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 |