]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/poly_collection/detail/packed_segment.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / poly_collection / detail / packed_segment.hpp
CommitLineData
92f5a8d4 1/* Copyright 2016-2018 Joaquin M Lopez Munoz.
b32b8144
FG
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * See http://www.boost.org/libs/poly_collection for library home page.
7 */
8
9#ifndef BOOST_POLY_COLLECTION_DETAIL_PACKED_SEGMENT_HPP
10#define BOOST_POLY_COLLECTION_DETAIL_PACKED_SEGMENT_HPP
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/detail/workaround.hpp>
b32b8144
FG
17#include <boost/poly_collection/detail/segment_backend.hpp>
18#include <boost/poly_collection/detail/value_holder.hpp>
19#include <memory>
20#include <new>
21#include <vector>
22#include <utility>
23
24namespace boost{
25
26namespace poly_collection{
27
28namespace detail{
29
30/* segment_backend implementation where value_type& and Concrete& actually refer
31 * to the same stored entity.
32 *
33 * Requires:
34 * - [const_]base_iterator is a stride iterator constructible from
35 * {value_type*,sizeof(store_value_type)}.
36 * - Model provides a function value_ptr for
37 * const Concrete* -> const value_type* conversion.
38 */
39
40template<typename Model,typename Concrete,typename Allocator>
92f5a8d4 41class packed_segment:public segment_backend<Model,Allocator>
b32b8144
FG
42{
43 using value_type=typename Model::value_type;
44 using store_value_type=value_holder<Concrete>;
45 using store=std::vector<
46 store_value_type,
92f5a8d4
TL
47 typename std::allocator_traits<Allocator>::
48 template rebind_alloc<store_value_type>
b32b8144
FG
49 >;
50 using store_iterator=typename store::iterator;
51 using const_store_iterator=typename store::const_iterator;
92f5a8d4 52 using segment_backend=detail::segment_backend<Model,Allocator>;
b32b8144
FG
53 using typename segment_backend::segment_backend_unique_ptr;
54 using typename segment_backend::value_pointer;
55 using typename segment_backend::const_value_pointer;
56 using typename segment_backend::base_iterator;
57 using typename segment_backend::const_base_iterator;
58 using const_iterator=
59 typename segment_backend::template const_iterator<Concrete>;
60 using typename segment_backend::base_sentinel;
61 using typename segment_backend::range;
92f5a8d4
TL
62 using segment_allocator_type=typename std::allocator_traits<Allocator>::
63 template rebind_alloc<packed_segment>;
64
b32b8144
FG
65public:
66 virtual ~packed_segment()=default;
67
92f5a8d4
TL
68 static segment_backend_unique_ptr make(const segment_allocator_type& al)
69 {
70 return new_(al,al);
71 }
72
b32b8144
FG
73 virtual segment_backend_unique_ptr copy()const
74 {
75 return new_(s.get_allocator(),store{s});
76 }
77
92f5a8d4 78 virtual segment_backend_unique_ptr copy(const Allocator& al)const
b32b8144 79 {
92f5a8d4
TL
80 return new_(al,store{s,al});
81 }
82
83 virtual segment_backend_unique_ptr empty_copy(const Allocator& al)const
84 {
85 return new_(al,al);
86 }
87
88 virtual segment_backend_unique_ptr move(const Allocator& al)const
89 {
90 return new_(al,store{std::move(s),al});
b32b8144
FG
91 }
92
93 virtual bool equal(const segment_backend& x)const
94 {
95 return s==static_cast<const packed_segment&>(x).s;
96 }
97
92f5a8d4
TL
98 virtual Allocator get_allocator()const noexcept{return s.get_allocator();}
99
b32b8144
FG
100 virtual base_iterator begin()const noexcept{return nv_begin();}
101
102 base_iterator nv_begin()const noexcept
103 {
104 return {value_ptr(s.data()),sizeof(store_value_type)};
105 }
106
107 virtual base_iterator end()const noexcept{return nv_end();}
108
109 base_iterator nv_end()const noexcept
110 {
111 return {value_ptr(s.data()+s.size()),sizeof(store_value_type)};
112 }
113
114 virtual bool empty()const noexcept{return nv_empty();}
115 bool nv_empty()const noexcept{return s.empty();}
116 virtual std::size_t size()const noexcept{return nv_size();}
117 std::size_t nv_size()const noexcept{return s.size();}
118 virtual std::size_t max_size()const noexcept{return nv_max_size();}
119 std::size_t nv_max_size()const noexcept{return s.max_size();}
120 virtual std::size_t capacity()const noexcept{return nv_capacity();}
121 std::size_t nv_capacity()const noexcept{return s.capacity();}
122 virtual base_sentinel reserve(std::size_t n){return nv_reserve(n);}
123 base_sentinel nv_reserve(std::size_t n)
124 {s.reserve(n);return sentinel();}
125 virtual base_sentinel shrink_to_fit(){return nv_shrink_to_fit();}
126 base_sentinel nv_shrink_to_fit()
127 {s.shrink_to_fit();return sentinel();}
128
129 template<typename Iterator,typename... Args>
130 range nv_emplace(Iterator p,Args&&... args)
131 {
132 return range_from(
133 s.emplace(
134 iterator_from(p),
135 value_holder_emplacing_ctor,std::forward<Args>(args)...));
136 }
137
138 template<typename... Args>
139 range nv_emplace_back(Args&&... args)
140 {
141 s.emplace_back(value_holder_emplacing_ctor,std::forward<Args>(args)...);
142 return range_from(s.size()-1);
143 }
144
145 virtual range push_back(const_value_pointer x)
146 {return nv_push_back(const_concrete_ref(x));}
147
148 range nv_push_back(const Concrete& x)
149 {
150 s.emplace_back(x);
151 return range_from(s.size()-1);
152 }
153
154 virtual range push_back_move(value_pointer x)
155 {return nv_push_back(std::move(concrete_ref(x)));}
156
157 range nv_push_back(Concrete&& x)
158 {
159 s.emplace_back(std::move(x));
160 return range_from(s.size()-1);
161 }
162
163 virtual range insert(const_base_iterator p,const_value_pointer x)
164 {return nv_insert(const_iterator(p),const_concrete_ref(x));}
165
166 range nv_insert(const_iterator p,const Concrete& x)
167 {
168 return range_from(s.emplace(iterator_from(p),x));
169 }
170
171 virtual range insert_move(const_base_iterator p,value_pointer x)
172 {return nv_insert(const_iterator(p),std::move(concrete_ref(x)));}
173
174 range nv_insert(const_iterator p,Concrete&& x)
175 {
176 return range_from(s.emplace(iterator_from(p),std::move(x)));
177 }
178
179 template<typename InputIterator>
180 range nv_insert(InputIterator first,InputIterator last)
181 {
182 return nv_insert(
183 const_iterator(concrete_ptr(s.data()+s.size())),first,last);
184 }
185
186 template<typename InputIterator>
187 range nv_insert(const_iterator p,InputIterator first,InputIterator last)
188 {
189#if BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION,<40900)
190 /* std::vector::insert(pos,first,last) returns void rather than iterator */
191
192 auto n=const_store_value_type_ptr(p)-s.data();
193 s.insert(s.begin()+n,first,last);
194 return range_from(static_cast<std::size_t>(n));
195#else
196 return range_from(s.insert(iterator_from(p),first,last));
197#endif
198 }
199
200 virtual range erase(const_base_iterator p)
201 {return nv_erase(const_iterator(p));}
202
203 range nv_erase(const_iterator p)
204 {
205 return range_from(s.erase(iterator_from(p)));
206 }
207
208 virtual range erase(const_base_iterator first,const_base_iterator last)
209 {return nv_erase(const_iterator(first),const_iterator(last));}
210
211 range nv_erase(const_iterator first,const_iterator last)
212 {
213 return range_from(s.erase(iterator_from(first),iterator_from(last)));
214 }
215
216 virtual range erase_till_end(const_base_iterator first)
217 {
218 return range_from(s.erase(iterator_from(first),s.end()));
219 }
220
221 virtual range erase_from_begin(const_base_iterator last)
222 {
223 return range_from(s.erase(s.begin(),iterator_from(last)));
224 }
225
226 virtual base_sentinel clear()noexcept{return nv_clear();}
227 base_sentinel nv_clear()noexcept{s.clear();return sentinel();}
228
229private:
b32b8144
FG
230 template<typename... Args>
231 static segment_backend_unique_ptr new_(
232 segment_allocator_type al,Args&&... args)
233 {
234 auto p=std::allocator_traits<segment_allocator_type>::allocate(al,1);
235 try{
236 ::new ((void*)p) packed_segment{std::forward<Args>(args)...};
237 }
238 catch(...){
239 std::allocator_traits<segment_allocator_type>::deallocate(al,p,1);
240 throw;
241 }
242 return {p,&delete_};
243 }
244
245 static void delete_(segment_backend* p)
246 {
247 auto q=static_cast<packed_segment*>(p);
248 auto al=segment_allocator_type{q->s.get_allocator()};
249 q->~packed_segment();
250 std::allocator_traits<segment_allocator_type>::deallocate(al,q,1);
251 }
252
253 packed_segment(const Allocator& al):s{typename store::allocator_type{al}}{}
254 packed_segment(store&& s):s{std::move(s)}{}
255
256 static Concrete& concrete_ref(value_pointer p)noexcept
257 {
258 return *static_cast<Concrete*>(p);
259 }
260
261 static const Concrete& const_concrete_ref(const_value_pointer p)noexcept
262 {
263 return *static_cast<const Concrete*>(p);
264 }
265
266 static Concrete* concrete_ptr(store_value_type* p)noexcept
267 {
268 return reinterpret_cast<Concrete*>(
269 static_cast<value_holder_base<Concrete>*>(p));
270 }
271
272 static const Concrete* const_concrete_ptr(const store_value_type* p)noexcept
273 {
274 return concrete_ptr(const_cast<store_value_type*>(p));
275 }
276
277 static value_type* value_ptr(const store_value_type* p)noexcept
278 {
279 return const_cast<value_type*>(Model::value_ptr(const_concrete_ptr(p)));
280 }
281
282 static const store_value_type* const_store_value_type_ptr(
283 const Concrete* p)noexcept
284 {
285 return static_cast<const value_holder<Concrete>*>(
286 reinterpret_cast<const value_holder_base<Concrete>*>(p));
287 }
288
289 /* It would have sufficed if iterator_from returned const_store_iterator
290 * except for the fact that some old versions of libstdc++ claiming to be
291 * C++11 compliant do not however provide std::vector modifier ops taking
292 * const_iterator's.
293 */
294
295 store_iterator iterator_from(const_base_iterator p)
296 {
297 return iterator_from(static_cast<const_iterator>(p));
298 }
299
300 store_iterator iterator_from(const_iterator p)
301 {
302 return s.begin()+(const_store_value_type_ptr(p)-s.data());
303 }
304
305 base_sentinel sentinel()const noexcept
306 {
307 return base_iterator{
308 value_ptr(s.data()+s.size()),
309 sizeof(store_value_type)
310 };
311 }
312
313 range range_from(const_store_iterator it)const
314 {
315 return {
316 {value_ptr(s.data()+(it-s.begin())),sizeof(store_value_type)},
317 sentinel()
318 };
319 }
320
321 range range_from(std::size_t n)const
322 {
323 return {
324 {value_ptr(s.data()+n),sizeof(store_value_type)},
325 sentinel()
326 };
327 }
328
329 store s;
330};
331
332} /* namespace poly_collection::detail */
333
334} /* namespace poly_collection */
335
336} /* namespace boost */
337
338#endif