]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/container/pmr/resource_adaptor.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / container / pmr / resource_adaptor.hpp
CommitLineData
7c673cae
FG
1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
4// Software License, Version 1.0. (See accompanying file
5// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// See http://www.boost.org/libs/container for documentation.
8//
9//////////////////////////////////////////////////////////////////////////////
10
11#ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
12#define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
13
14#if defined (_MSC_VER)
15# pragma once
16#endif
17
92f5a8d4
TL
18#include <boost/container/detail/config_begin.hpp>
19#include <boost/container/detail/workaround.hpp>
20#include <boost/container/container_fwd.hpp>
21
7c673cae
FG
22#include <boost/container/pmr/memory_resource.hpp>
23#include <boost/container/allocator_traits.hpp>
24#include <boost/intrusive/detail/ebo_functor_holder.hpp>
25#include <boost/move/utility_core.hpp>
92f5a8d4
TL
26#include <boost/move/detail/type_traits.hpp>
27#include <boost/container/detail/std_fwd.hpp>
28
29#include <cstring>
7c673cae
FG
30
31namespace boost {
32namespace container {
92f5a8d4
TL
33
34namespace pmr_dtl {
35
36template<class T>
37struct max_allocator_alignment
38{
39 static const std::size_t value = 1;
40};
41
42template<class T>
43struct max_allocator_alignment< ::boost::container::new_allocator<T> >
44{
45 static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
46};
47
48template<class T>
49struct max_allocator_alignment< std::allocator<T> >
50{
51 static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
52};
53
54} //namespace pmr_dtl
55
7c673cae
FG
56namespace pmr {
57
58//! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
59//! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
60//! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
61//! an alias to this class template such that Allocator is rebound to a char value type in every
62//! specialization of the class template. The requirements on this class template are defined below.
63//! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
64//! the following additional requirements:
65//!
66//! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
67//! `typename allocator_traits<Allocator>:: value_type*`.
68//!
69//! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
70//! `typename allocator_traits<Allocator>:: value_type const*`.
71//!
72//! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
73//!
74//! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
75template <class Allocator>
76class resource_adaptor_imp
77 : public memory_resource
78 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
79 , private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
80 #endif
81{
82 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
83 Allocator m_alloc;
84 #else
85 BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
86 typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
87 void static_assert_if_not_char_allocator() const
88 {
89 //This class can only be used with allocators type char
92f5a8d4 90 BOOST_STATIC_ASSERT((boost::container::dtl::is_same<typename Allocator::value_type, char>::value));
7c673cae
FG
91 }
92 #endif
93
94 public:
95 typedef Allocator allocator_type;
96
97 //! <b>Effects</b>: Default constructs
98 //! m_alloc.
99 resource_adaptor_imp()
100 { this->static_assert_if_not_char_allocator(); }
101
102 //! <b>Effects</b>: Copy constructs
103 //! m_alloc.
104 resource_adaptor_imp(const resource_adaptor_imp &other)
105 : ebo_alloc_t(other.ebo_alloc_t::get())
106 {}
107
108 //! <b>Effects</b>: Move constructs
109 //! m_alloc.
110 resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
111 : ebo_alloc_t(::boost::move(other.get()))
112 {}
113
114 //! <b>Effects</b>: Initializes m_alloc with
115 //! a2.
116 explicit resource_adaptor_imp(const Allocator& a2)
117 : ebo_alloc_t(a2)
118 { this->static_assert_if_not_char_allocator(); }
119
120 //! <b>Effects</b>: Initializes m_alloc with
121 //! a2.
122 explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
123 : ebo_alloc_t(::boost::move(a2))
124 { this->static_assert_if_not_char_allocator(); }
125
126 //! <b>Effects</b>: Copy assigns
127 //! m_alloc.
128 resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
129 { this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this; }
130
131 //! <b>Effects</b>: Move assigns
132 //! m_alloc.
133 resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
134 { this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this; }
135
136 //! <b>Effects</b>: Returns m_alloc.
137 allocator_type &get_allocator()
138 { return this->ebo_alloc_t::get(); }
139
140 //! <b>Effects</b>: Returns m_alloc.
141 const allocator_type &get_allocator() const
142 { return this->ebo_alloc_t::get(); }
143
144 protected:
145 //! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
146 //! of the allocated memory shall meet the requirements for a class derived from memory_resource.
92f5a8d4
TL
147 virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
148 {
149 if (alignment <= priv_guaranteed_allocator_alignment())
150 return this->ebo_alloc_t::get().allocate(bytes);
151 else
152 return this->priv_aligned_alloc(bytes, alignment);
153 }
7c673cae
FG
154
155 //! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
156 //! subsequently deallocated.
157 //!
158 //! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
92f5a8d4
TL
159 virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
160 {
161 if (alignment <= priv_guaranteed_allocator_alignment())
162 this->ebo_alloc_t::get().deallocate((char*)p, bytes);
163 else
164 this->priv_aligned_dealloc(p, bytes, alignment);
165 }
7c673cae
FG
166
167 //! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
168 //!
169 //! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
170 virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
171 {
172 const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
173 return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
174 }
92f5a8d4
TL
175
176 private:
177 void * priv_aligned_alloc(std::size_t bytes, std::size_t alignment)
178 {
179 //Allocate space for requested bytes, plus alignment, plus bookeeping data
180 void *const p = this->ebo_alloc_t::get().allocate(bytes + priv_extra_bytes_for_overalignment(alignment));
181
182 if (0 != p) {
183 //Obtain the aligned address after the bookeeping data
184 void *const aligned_ptr = (void*)(((std::size_t)p + priv_extra_bytes_for_overalignment(alignment)) & ~(alignment - 1));
185
186 //Store bookeeping data. Use memcpy as the underlying memory might be unaligned for
187 //a pointer (e.g. 2 byte alignment in 32 bit, 4 byte alignment in 64 bit)
188 std::memcpy(priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), &p, sizeof(p));
189 return aligned_ptr;
190 }
191 return 0;
192 }
193
194 void priv_aligned_dealloc(void *aligned_ptr, std::size_t bytes, std::size_t alignment)
195 {
196 //Obtain bookeeping data
197 void *p;
198 std::memcpy(&p, priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), sizeof(p));
199 std::size_t s = bytes + priv_extra_bytes_for_overalignment(alignment);
200 this->ebo_alloc_t::get().deallocate((char*)p, s);
201 }
202
203 static BOOST_CONTAINER_FORCEINLINE void *priv_bookeeping_addr_from_aligned_ptr(void *aligned_ptr)
204 {
205 return reinterpret_cast<void*>(reinterpret_cast<std::size_t>(aligned_ptr) - sizeof(void*));
206 }
207
208 BOOST_CONTAINER_FORCEINLINE static std::size_t priv_extra_bytes_for_overalignment(std::size_t alignment)
209 {
210 return alignment - 1 + sizeof(void*);
211 }
212
213 BOOST_CONTAINER_FORCEINLINE static std::size_t priv_guaranteed_allocator_alignment()
214 {
215 return pmr_dtl::max_allocator_alignment<Allocator>::value;
216 }
7c673cae
FG
217};
218
219#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
220
221//! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
222//! such that Allocator is rebound to a char value type.
223template <class Allocator>
224using resource_adaptor = resource_adaptor_imp
225 <typename allocator_traits<Allocator>::template rebind_alloc<char> >;
226
227#else
228
229template <class Allocator>
230class resource_adaptor
231 : public resource_adaptor_imp
232 <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
233{
234 typedef resource_adaptor_imp
235 <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
236
237 BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
238
239 public:
240 resource_adaptor()
241 : base_t()
242 {}
243
244 resource_adaptor(const resource_adaptor &other)
245 : base_t(other)
246 {}
247
248 resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
249 : base_t(BOOST_MOVE_BASE(base_t, other))
250 {}
251
252 explicit resource_adaptor(const Allocator& a2)
253 : base_t(a2)
254 {}
255
256 explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
92f5a8d4 257 : base_t(::boost::move(a2))
7c673cae
FG
258 {}
259
260 resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
261 { return static_cast<resource_adaptor&>(this->base_t::operator=(other)); }
262
263 resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
264 { return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other))); }
265
266 //get_allocator and protected functions are properly inherited
267};
268
269#endif
270
271} //namespace pmr {
272} //namespace container {
273} //namespace boost {
274
92f5a8d4
TL
275#include <boost/container/detail/config_end.hpp>
276
7c673cae 277#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP