]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/smart_ptr/allocate_shared_array.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / smart_ptr / allocate_shared_array.hpp
1 /*
2 Copyright 2012-2017 Glen Joseph Fernandes
3 (glenjofe@gmail.com)
4
5 Distributed under the Boost Software License, Version 1.0.
6 (http://www.boost.org/LICENSE_1_0.txt)
7 */
8 #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
9 #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
10
11 #include <boost/smart_ptr/shared_ptr.hpp>
12 #include <boost/type_traits/alignment_of.hpp>
13 #include <boost/type_traits/has_trivial_assign.hpp>
14 #include <boost/type_traits/has_trivial_constructor.hpp>
15 #include <boost/type_traits/has_trivial_destructor.hpp>
16 #include <boost/type_traits/type_with_alignment.hpp>
17
18 namespace boost {
19 namespace detail {
20
21 template<class>
22 struct sp_if_array { };
23
24 template<class T>
25 struct sp_if_array<T[]> {
26 typedef boost::shared_ptr<T[]> type;
27 };
28
29 template<class>
30 struct sp_if_size_array { };
31
32 template<class T, std::size_t N>
33 struct sp_if_size_array<T[N]> {
34 typedef boost::shared_ptr<T[N]> type;
35 };
36
37 template<class>
38 struct sp_array_element { };
39
40 template<class T>
41 struct sp_array_element<T[]> {
42 typedef T type;
43 };
44
45 template<class T, std::size_t N>
46 struct sp_array_element<T[N]> {
47 typedef T type;
48 };
49
50 template<class T>
51 struct sp_array_scalar {
52 typedef T type;
53 };
54
55 template<class T, std::size_t N>
56 struct sp_array_scalar<T[N]> {
57 typedef typename sp_array_scalar<T>::type type;
58 };
59
60 template<class T, std::size_t N>
61 struct sp_array_scalar<const T[N]> {
62 typedef typename sp_array_scalar<T>::type type;
63 };
64
65 template<class T, std::size_t N>
66 struct sp_array_scalar<volatile T[N]> {
67 typedef typename sp_array_scalar<T>::type type;
68 };
69
70 template<class T, std::size_t N>
71 struct sp_array_scalar<const volatile T[N]> {
72 typedef typename sp_array_scalar<T>::type type;
73 };
74
75 template<class T>
76 struct sp_array_scalar<T[]> {
77 typedef typename sp_array_scalar<T>::type type;
78 };
79
80 template<class T>
81 struct sp_array_scalar<const T[]> {
82 typedef typename sp_array_scalar<T>::type type;
83 };
84
85 template<class T>
86 struct sp_array_scalar<volatile T[]> {
87 typedef typename sp_array_scalar<T>::type type;
88 };
89
90 template<class T>
91 struct sp_array_scalar<const volatile T[]> {
92 typedef typename sp_array_scalar<T>::type type;
93 };
94
95 template<class T>
96 struct sp_array_count {
97 enum {
98 value = 1
99 };
100 };
101
102 template<class T, std::size_t N>
103 struct sp_array_count<T[N]> {
104 enum {
105 value = N * sp_array_count<T>::value
106 };
107 };
108
109 template<std::size_t N, std::size_t M>
110 struct sp_max_size {
111 enum {
112 value = N < M ? M : N
113 };
114 };
115
116 template<std::size_t N, std::size_t M>
117 struct sp_align_up {
118 enum {
119 value = (N + M - 1) & ~(M - 1)
120 };
121 };
122
123 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
124 template<class A, class T>
125 struct sp_bind_allocator {
126 typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
127 };
128 #else
129 template<class A, class T>
130 struct sp_bind_allocator {
131 typedef typename A::template rebind<T>::other type;
132 };
133 #endif
134
135 template<class T>
136 BOOST_CONSTEXPR inline std::size_t
137 sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
138 {
139 return (size + sizeof(T) - 1) / sizeof(T);
140 }
141
142 template<bool, class = void>
143 struct sp_enable { };
144
145 template<class T>
146 struct sp_enable<true, T> {
147 typedef T type;
148 };
149
150 template<bool E, class A, class T>
151 inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type
152 sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
153
154 template<bool E, class A, class T>
155 inline typename sp_enable<!E &&
156 !boost::has_trivial_destructor<T>::value>::type
157 sp_array_destroy(A&, T* start, std::size_t size)
158 {
159 while (size > 0) {
160 start[--size].~T();
161 }
162 }
163
164 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
165 template<bool E, class A, class T>
166 inline typename sp_enable<E>::type
167 sp_array_destroy(A& allocator, T* start, std::size_t size)
168 {
169 while (size > 0) {
170 std::allocator_traits<A>::destroy(allocator, start + --size);
171 }
172 }
173 #endif
174
175 template<bool E, class A, class T>
176 inline typename sp_enable<!E &&
177 boost::has_trivial_constructor<T>::value &&
178 boost::has_trivial_assign<T>::value &&
179 boost::has_trivial_destructor<T>::value>::type
180 sp_array_construct(A&, T* start, std::size_t size)
181 {
182 for (std::size_t i = 0; i < size; ++i) {
183 start[i] = T();
184 }
185 }
186
187 template<bool E, class A, class T>
188 inline typename sp_enable<!E &&
189 boost::has_trivial_constructor<T>::value &&
190 boost::has_trivial_assign<T>::value &&
191 boost::has_trivial_destructor<T>::value>::type
192 sp_array_construct(A&, T* start, std::size_t size, const T* list,
193 std::size_t count)
194 {
195 for (std::size_t i = 0; i < size; ++i) {
196 start[i] = list[i % count];
197 }
198 }
199
200 #if !defined(BOOST_NO_EXCEPTIONS)
201 template<bool E, class A, class T>
202 inline typename sp_enable<!E &&
203 !(boost::has_trivial_constructor<T>::value &&
204 boost::has_trivial_assign<T>::value &&
205 boost::has_trivial_destructor<T>::value)>::type
206 sp_array_construct(A& none, T* start, std::size_t size)
207 {
208 std::size_t i = 0;
209 try {
210 for (; i < size; ++i) {
211 ::new(static_cast<void*>(start + i)) T();
212 }
213 } catch (...) {
214 sp_array_destroy<E>(none, start, i);
215 throw;
216 }
217 }
218
219 template<bool E, class A, class T>
220 inline typename sp_enable<!E &&
221 !(boost::has_trivial_constructor<T>::value &&
222 boost::has_trivial_assign<T>::value &&
223 boost::has_trivial_destructor<T>::value)>::type
224 sp_array_construct(A& none, T* start, std::size_t size, const T* list,
225 std::size_t count)
226 {
227 std::size_t i = 0;
228 try {
229 for (; i < size; ++i) {
230 ::new(static_cast<void*>(start + i)) T(list[i % count]);
231 }
232 } catch (...) {
233 sp_array_destroy<E>(none, start, i);
234 throw;
235 }
236 }
237 #else
238 template<bool E, class A, class T>
239 inline typename sp_enable<!E &&
240 !(boost::has_trivial_constructor<T>::value &&
241 boost::has_trivial_assign<T>::value &&
242 boost::has_trivial_destructor<T>::value)>::type
243 sp_array_construct(A&, T* start, std::size_t size)
244 {
245 for (std::size_t i = 0; i < size; ++i) {
246 ::new(static_cast<void*>(start + i)) T();
247 }
248 }
249
250 template<bool E, class A, class T>
251 inline typename sp_enable<!E &&
252 !(boost::has_trivial_constructor<T>::value &&
253 boost::has_trivial_assign<T>::value &&
254 boost::has_trivial_destructor<T>::value)>::type
255 sp_array_construct(A&, T* start, std::size_t size, const T* list,
256 std::size_t count)
257 {
258 for (std::size_t i = 0; i < size; ++i) {
259 ::new(static_cast<void*>(start + i)) T(list[i % count]);
260 }
261 }
262 #endif
263
264 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
265 #if !defined(BOOST_NO_EXCEPTIONS)
266 template<bool E, class A, class T>
267 inline typename sp_enable<E>::type
268 sp_array_construct(A& allocator, T* start, std::size_t size)
269 {
270 std::size_t i = 0;
271 try {
272 for (i = 0; i < size; ++i) {
273 std::allocator_traits<A>::construct(allocator, start + i);
274 }
275 } catch (...) {
276 sp_array_destroy<E>(allocator, start, i);
277 throw;
278 }
279 }
280
281 template<bool E, class A, class T>
282 inline typename sp_enable<E>::type
283 sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
284 std::size_t count)
285 {
286 std::size_t i = 0;
287 try {
288 for (i = 0; i < size; ++i) {
289 std::allocator_traits<A>::construct(allocator, start + i,
290 list[i % count]);
291 }
292 } catch (...) {
293 sp_array_destroy<E>(allocator, start, i);
294 throw;
295 }
296 }
297 #else
298 template<bool E, class A, class T>
299 inline typename sp_enable<E>::type
300 sp_array_construct(A& allocator, T* start, std::size_t size)
301 {
302 for (std::size_t i = 0; i < size; ++i) {
303 std::allocator_traits<A>::construct(allocator, start + i);
304 }
305 }
306
307 template<bool E, class A, class T>
308 inline typename sp_enable<E>::type
309 sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
310 std::size_t count)
311 {
312 for (std::size_t i = 0; i < size; ++i) {
313 std::allocator_traits<A>::construct(allocator, start + i,
314 list[i % count]);
315 }
316 }
317 #endif
318 #endif
319
320 template<class A, class T>
321 inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type
322 sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
323
324 #if !defined(BOOST_NO_EXCEPTIONS)
325 template<class A, class T>
326 inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
327 sp_array_default(A& none, T* start, std::size_t size)
328 {
329 std::size_t i = 0;
330 try {
331 for (; i < size; ++i) {
332 ::new(static_cast<void*>(start + i)) T;
333 }
334 } catch (...) {
335 sp_array_destroy<false>(none, start, i);
336 throw;
337 }
338 }
339 #else
340 template<bool E, class A, class T>
341 inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
342 sp_array_default(A&, T* start, std::size_t size)
343 {
344 for (std::size_t i = 0; i < size; ++i) {
345 ::new(static_cast<void*>(start + i)) T;
346 }
347 }
348 #endif
349
350 template<class A>
351 class sp_array_state {
352 public:
353 typedef A type;
354
355 template<class U>
356 sp_array_state(const U& allocator, std::size_t size) BOOST_SP_NOEXCEPT
357 : allocator_(allocator),
358 size_(size) { }
359
360 A& allocator() BOOST_SP_NOEXCEPT {
361 return allocator_;
362 }
363
364 std::size_t size() const BOOST_SP_NOEXCEPT {
365 return size_;
366 }
367
368 private:
369 A allocator_;
370 std::size_t size_;
371 };
372
373 template<class A, std::size_t N>
374 class sp_size_array_state {
375 public:
376 typedef A type;
377
378 template<class U>
379 sp_size_array_state(const U& allocator, std::size_t) BOOST_SP_NOEXCEPT
380 : allocator_(allocator) { }
381
382 A& allocator() BOOST_SP_NOEXCEPT {
383 return allocator_;
384 }
385
386 BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
387 return N;
388 }
389
390 private:
391 A allocator_;
392 };
393
394 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
395 template<class A>
396 struct sp_use_construct {
397 enum {
398 value = true
399 };
400 };
401
402 template<class T>
403 struct sp_use_construct<std::allocator<T> > {
404 enum {
405 value = false
406 };
407 };
408 #else
409 template<class>
410 struct sp_use_construct {
411 enum {
412 value = false
413 };
414 };
415 #endif
416
417 template<class T, class U>
418 struct sp_array_alignment {
419 enum {
420 value = sp_max_size<boost::alignment_of<T>::value,
421 boost::alignment_of<U>::value>::value
422 };
423 };
424
425 template<class T, class U>
426 struct sp_array_offset {
427 enum {
428 value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value
429 };
430 };
431
432 template<class T, class U>
433 struct sp_array_storage {
434 enum {
435 value = sp_array_alignment<T, U>::value
436 };
437 typedef typename boost::type_with_alignment<value>::type type;
438 };
439
440 template<class T, class U>
441 inline U*
442 sp_array_start(void* base) BOOST_SP_NOEXCEPT
443 {
444 enum {
445 size = sp_array_offset<T, U>::value
446 };
447 return reinterpret_cast<U*>(static_cast<char*>(base) + size);
448 }
449
450 template<class A, class T>
451 class sp_array_creator {
452 typedef typename A::value_type scalar;
453
454 enum {
455 offset = sp_array_offset<T, scalar>::value
456 };
457
458 typedef typename sp_array_storage<T, scalar>::type type;
459
460 public:
461 template<class U>
462 sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
463 : other_(other),
464 size_(sp_objects<type>(offset + sizeof(scalar) * size)) { }
465
466 T* create() {
467 return reinterpret_cast<T*>(other_.allocate(size_));
468 }
469
470 void destroy(T* base) {
471 other_.deallocate(reinterpret_cast<type*>(base), size_);
472 }
473
474 private:
475 typename sp_bind_allocator<A, type>::type other_;
476 std::size_t size_;
477 };
478
479 struct sp_default { };
480
481 template<class T, bool E = sp_use_construct<T>::value>
482 class sp_array_base
483 : public sp_counted_base {
484 typedef typename T::type allocator;
485
486 public:
487 typedef typename allocator::value_type type;
488
489 template<class A>
490 sp_array_base(const A& other, std::size_t size, type* start)
491 : state_(other, size) {
492 sp_array_construct<E>(state_.allocator(), start, state_.size());
493 }
494
495 template<class A>
496 sp_array_base(const A& other, std::size_t size, const type* list,
497 std::size_t count, type* start)
498 : state_(other, size) {
499 sp_array_construct<E>(state_.allocator(), start, state_.size(), list,
500 count);
501 }
502
503 template<class A>
504 sp_array_base(sp_default, const A& other, std::size_t size, type* start)
505 : state_(other, size) {
506 sp_array_default(state_.allocator(), start, state_.size());
507 }
508
509 T& state() BOOST_SP_NOEXCEPT {
510 return state_;
511 }
512
513 virtual void dispose() {
514 sp_array_destroy<E>(state_.allocator(),
515 sp_array_start<sp_array_base, type>(this), state_.size());
516 }
517
518 virtual void destroy() {
519 sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
520 state_.size());
521 this->~sp_array_base();
522 other.destroy(this);
523 }
524
525 virtual void* get_deleter(const sp_typeinfo&) {
526 return 0;
527 }
528
529 virtual void* get_local_deleter(const sp_typeinfo&) {
530 return 0;
531 }
532
533 virtual void* get_untyped_deleter() {
534 return 0;
535 }
536
537 private:
538 T state_;
539 };
540
541 template<class A, class T>
542 struct sp_array_result {
543 public:
544 template<class U>
545 sp_array_result(const U& other, std::size_t size)
546 : creator_(other, size),
547 result_(creator_.create()) { }
548
549 ~sp_array_result() {
550 if (result_) {
551 creator_.destroy(result_);
552 }
553 }
554
555 T* get() const {
556 return result_;
557 }
558
559 void release() {
560 result_ = 0;
561 }
562
563 private:
564 sp_array_result(const sp_array_result&);
565 sp_array_result& operator=(const sp_array_result&);
566
567 sp_array_creator<A, T> creator_;
568 T* result_;
569 };
570
571 } /* detail */
572
573 template<class T, class A>
574 inline typename detail::sp_if_array<T>::type
575 allocate_shared(const A& allocator, std::size_t count)
576 {
577 typedef typename detail::sp_array_element<T>::type type;
578 typedef typename detail::sp_array_scalar<T>::type scalar;
579 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
580 typedef detail::sp_array_state<other> state;
581 typedef detail::sp_array_base<state> base;
582 std::size_t size = count * detail::sp_array_count<type>::value;
583 detail::sp_array_result<other, base> result(allocator, size);
584 detail::sp_counted_base* node = result.get();
585 scalar* start = detail::sp_array_start<base, scalar>(node);
586 ::new(static_cast<void*>(node)) base(allocator, size, start);
587 result.release();
588 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
589 reinterpret_cast<type*>(start), detail::shared_count(node));
590 }
591
592 template<class T, class A>
593 inline typename detail::sp_if_size_array<T>::type
594 allocate_shared(const A& allocator)
595 {
596 enum {
597 size = detail::sp_array_count<T>::value
598 };
599 typedef typename detail::sp_array_element<T>::type type;
600 typedef typename detail::sp_array_scalar<T>::type scalar;
601 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
602 typedef detail::sp_size_array_state<other, size> state;
603 typedef detail::sp_array_base<state> base;
604 detail::sp_array_result<other, base> result(allocator, size);
605 detail::sp_counted_base* node = result.get();
606 scalar* start = detail::sp_array_start<base, scalar>(node);
607 ::new(static_cast<void*>(node)) base(allocator, size, start);
608 result.release();
609 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
610 reinterpret_cast<type*>(start), detail::shared_count(node));
611 }
612
613 template<class T, class A>
614 inline typename detail::sp_if_array<T>::type
615 allocate_shared(const A& allocator, std::size_t count,
616 const typename detail::sp_array_element<T>::type& value)
617 {
618 typedef typename detail::sp_array_element<T>::type type;
619 typedef typename detail::sp_array_scalar<T>::type scalar;
620 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
621 typedef detail::sp_array_state<other> state;
622 typedef detail::sp_array_base<state> base;
623 std::size_t size = count * detail::sp_array_count<type>::value;
624 detail::sp_array_result<other, base> result(allocator, size);
625 detail::sp_counted_base* node = result.get();
626 scalar* start = detail::sp_array_start<base, scalar>(node);
627 ::new(static_cast<void*>(node)) base(allocator, size,
628 reinterpret_cast<const scalar*>(&value),
629 detail::sp_array_count<type>::value, start);
630 result.release();
631 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
632 reinterpret_cast<type*>(start), detail::shared_count(node));
633 }
634
635 template<class T, class A>
636 inline typename detail::sp_if_size_array<T>::type
637 allocate_shared(const A& allocator,
638 const typename detail::sp_array_element<T>::type& value)
639 {
640 enum {
641 size = detail::sp_array_count<T>::value
642 };
643 typedef typename detail::sp_array_element<T>::type type;
644 typedef typename detail::sp_array_scalar<T>::type scalar;
645 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
646 typedef detail::sp_size_array_state<other, size> state;
647 typedef detail::sp_array_base<state> base;
648 detail::sp_array_result<other, base> result(allocator, size);
649 detail::sp_counted_base* node = result.get();
650 scalar* start = detail::sp_array_start<base, scalar>(node);
651 ::new(static_cast<void*>(node)) base(allocator, size,
652 reinterpret_cast<const scalar*>(&value),
653 detail::sp_array_count<type>::value, start);
654 result.release();
655 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
656 reinterpret_cast<type*>(start), detail::shared_count(node));
657 }
658
659 template<class T, class A>
660 inline typename detail::sp_if_array<T>::type
661 allocate_shared_noinit(const A& allocator, std::size_t count)
662 {
663 typedef typename detail::sp_array_element<T>::type type;
664 typedef typename detail::sp_array_scalar<T>::type scalar;
665 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
666 typedef detail::sp_array_state<other> state;
667 typedef detail::sp_array_base<state, false> base;
668 std::size_t size = count * detail::sp_array_count<type>::value;
669 detail::sp_array_result<other, base> result(allocator, size);
670 detail::sp_counted_base* node = result.get();
671 scalar* start = detail::sp_array_start<base, scalar>(node);
672 ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
673 size, start);
674 result.release();
675 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
676 reinterpret_cast<type*>(start), detail::shared_count(node));
677 }
678
679 template<class T, class A>
680 inline typename detail::sp_if_size_array<T>::type
681 allocate_shared_noinit(const A& allocator)
682 {
683 enum {
684 size = detail::sp_array_count<T>::value
685 };
686 typedef typename detail::sp_array_element<T>::type type;
687 typedef typename detail::sp_array_scalar<T>::type scalar;
688 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
689 typedef detail::sp_size_array_state<other, size> state;
690 typedef detail::sp_array_base<state, false> base;
691 detail::sp_array_result<other, base> result(allocator, size);
692 detail::sp_counted_base* node = result.get();
693 scalar* start = detail::sp_array_start<base, scalar>(node);
694 ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
695 size, start);
696 result.release();
697 return shared_ptr<T>(detail::sp_internal_constructor_tag(),
698 reinterpret_cast<type*>(start), detail::shared_count(node));
699 }
700
701 } /* boost */
702
703 #endif