1 /* Copyright 2003-2020 Joaquin M Lopez Munoz.
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/multi_index for library home page.
7 */
8
9 #ifndef BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP
11
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <algorithm>
18 #include <boost/multi_index/detail/adl_swap.hpp>
19 #include <boost/multi_index/detail/allocator_traits.hpp>
20 #include <boost/noncopyable.hpp>
21 #include <boost/type_traits/integral_constant.hpp>
22 #include <memory>
23
24 namespace boost{
25
26 namespace multi_index{
27
28 namespace detail{
29
30 /* auto_space provides uninitialized space suitably to store
31 * a given number of elements of a given type.
32 */
33
34 /* NB: it is not clear whether using an allocator to handle
35 * zero-sized arrays of elements is conformant or not. GCC 3.3.1
36 * and prior fail here, other stdlibs handle the issue gracefully.
37 * To be on the safe side, the case n==0 is given special treatment.
38 * References:
39 * GCC Bugzilla, "standard allocator crashes when deallocating segment
40 * "of zero length", http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14176
41 * C++ Standard Library Defect Report List (Revision 28), issue 199
42 * "What does allocate(0) return?",
43 * http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#199
44 */
45
46 template<typename T,typename Allocator=std::allocator<T> >
47 struct auto_space:private noncopyable
48 {
49 typedef typename rebind_alloc_for<
50 Allocator,T>
51 ::type allocator;
52 typedef allocator_traits<allocator> alloc_traits;
53 typedef typename alloc_traits::pointer pointer;
54 typedef typename alloc_traits::size_type size_type;
55
auto_spaceboost::multi_index::detail::auto_space56 explicit auto_space(const Allocator& al=Allocator(),size_type n=1):
57 al_(al),n_(n),data_(n_?alloc_traits::allocate(al_,n_):pointer(0))
58 {}
59
~auto_spaceboost::multi_index::detail::auto_space60 ~auto_space(){if(n_)alloc_traits::deallocate(al_,data_,n_);}
61
get_allocatorboost::multi_index::detail::auto_space62 Allocator get_allocator()const{return al_;}
63
databoost::multi_index::detail::auto_space64 pointer data()const{return data_;}
65
swapboost::multi_index::detail::auto_space66 void swap(auto_space& x)
67 {
68 swap(
69 x,
70 boost::integral_constant<
71 bool,alloc_traits::propagate_on_container_swap::value>());
72 }
73
swapboost::multi_index::detail::auto_space74 void swap(auto_space& x,boost::true_type /* swap_allocators */)
75 {
76 adl_swap(al_,x.al_);
77 std::swap(n_,x.n_);
78 std::swap(data_,x.data_);
79 }
80
swapboost::multi_index::detail::auto_space81 void swap(auto_space& x,boost::false_type /* swap_allocators */)
82 {
83 std::swap(n_,x.n_);
84 std::swap(data_,x.data_);
85 }
86
87 private:
88 allocator al_;
89 size_type n_;
90 pointer data_;
91 };
92
93 template<typename T,typename Allocator>
swap(auto_space<T,Allocator> & x,auto_space<T,Allocator> & y)94 void swap(auto_space<T,Allocator>& x,auto_space<T,Allocator>& y)
95 {
96 x.swap(y);
97 }
98
99 } /* namespace multi_index::detail */
100
101 } /* namespace multi_index */
102
103 } /* namespace boost */
104
105 #endif
106