Chris@102
|
1 /*
|
Chris@102
|
2 (c) 2014 Glen Joseph Fernandes
|
Chris@102
|
3 glenjofe at gmail dot com
|
Chris@102
|
4
|
Chris@102
|
5 Distributed under the Boost Software
|
Chris@102
|
6 License, Version 1.0.
|
Chris@102
|
7 http://boost.org/LICENSE_1_0.txt
|
Chris@102
|
8 */
|
Chris@102
|
9 #ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
|
Chris@102
|
10 #define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
|
Chris@102
|
11
|
Chris@102
|
12 #include <boost/config.hpp>
|
Chris@102
|
13 #include <boost/static_assert.hpp>
|
Chris@102
|
14 #include <boost/align/align.hpp>
|
Chris@102
|
15 #include <boost/align/aligned_allocator_adaptor_forward.hpp>
|
Chris@102
|
16 #include <boost/align/alignment_of.hpp>
|
Chris@102
|
17 #include <boost/align/detail/addressof.hpp>
|
Chris@102
|
18 #include <boost/align/detail/is_alignment_constant.hpp>
|
Chris@102
|
19 #include <boost/align/detail/max_align.hpp>
|
Chris@102
|
20 #include <new>
|
Chris@102
|
21
|
Chris@102
|
22 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@102
|
23 #include <memory>
|
Chris@102
|
24 #endif
|
Chris@102
|
25
|
Chris@102
|
26 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@102
|
27 #include <utility>
|
Chris@102
|
28 #endif
|
Chris@102
|
29
|
Chris@102
|
30 namespace boost {
|
Chris@102
|
31 namespace alignment {
|
Chris@102
|
32 template<class Allocator, std::size_t Alignment>
|
Chris@102
|
33 class aligned_allocator_adaptor
|
Chris@102
|
34 : public Allocator {
|
Chris@102
|
35 BOOST_STATIC_ASSERT(detail::
|
Chris@102
|
36 is_alignment_constant<Alignment>::value);
|
Chris@102
|
37
|
Chris@102
|
38 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@102
|
39 typedef std::allocator_traits<Allocator> Traits;
|
Chris@102
|
40
|
Chris@102
|
41 typedef typename Traits::
|
Chris@102
|
42 template rebind_alloc<char> CharAlloc;
|
Chris@102
|
43
|
Chris@102
|
44 typedef typename Traits::
|
Chris@102
|
45 template rebind_traits<char> CharTraits;
|
Chris@102
|
46
|
Chris@102
|
47 typedef typename CharTraits::pointer CharPtr;
|
Chris@102
|
48 #else
|
Chris@102
|
49 typedef typename Allocator::
|
Chris@102
|
50 template rebind<char>::other CharAlloc;
|
Chris@102
|
51
|
Chris@102
|
52 typedef typename CharAlloc::pointer CharPtr;
|
Chris@102
|
53 #endif
|
Chris@102
|
54
|
Chris@102
|
55 public:
|
Chris@102
|
56 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@102
|
57 typedef typename Traits::value_type value_type;
|
Chris@102
|
58 typedef typename Traits::size_type size_type;
|
Chris@102
|
59 #else
|
Chris@102
|
60 typedef typename Allocator::value_type value_type;
|
Chris@102
|
61 typedef typename Allocator::size_type size_type;
|
Chris@102
|
62 #endif
|
Chris@102
|
63
|
Chris@102
|
64 typedef value_type* pointer;
|
Chris@102
|
65 typedef const value_type* const_pointer;
|
Chris@102
|
66 typedef void* void_pointer;
|
Chris@102
|
67 typedef const void* const_void_pointer;
|
Chris@102
|
68 typedef std::ptrdiff_t difference_type;
|
Chris@102
|
69
|
Chris@102
|
70 private:
|
Chris@102
|
71 typedef detail::max_align<Alignment,
|
Chris@102
|
72 detail::max_align<alignment_of<value_type>::value,
|
Chris@102
|
73 alignment_of<CharPtr>::value>::value> MaxAlign;
|
Chris@102
|
74
|
Chris@102
|
75 public:
|
Chris@102
|
76 template<class U>
|
Chris@102
|
77 struct rebind {
|
Chris@102
|
78 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@102
|
79 typedef aligned_allocator_adaptor<typename Traits::
|
Chris@102
|
80 template rebind_alloc<U>, Alignment> other;
|
Chris@102
|
81 #else
|
Chris@102
|
82 typedef aligned_allocator_adaptor<typename Allocator::
|
Chris@102
|
83 template rebind<U>::other, Alignment> other;
|
Chris@102
|
84 #endif
|
Chris@102
|
85 };
|
Chris@102
|
86
|
Chris@102
|
87 #if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
|
Chris@102
|
88 aligned_allocator_adaptor() = default;
|
Chris@102
|
89 #else
|
Chris@102
|
90 aligned_allocator_adaptor()
|
Chris@102
|
91 : Allocator() {
|
Chris@102
|
92 }
|
Chris@102
|
93 #endif
|
Chris@102
|
94
|
Chris@102
|
95 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
Chris@102
|
96 template<class A>
|
Chris@102
|
97 explicit aligned_allocator_adaptor(A&& alloc)
|
Chris@102
|
98 BOOST_NOEXCEPT
|
Chris@102
|
99 : Allocator(std::forward<A>(alloc)) {
|
Chris@102
|
100 }
|
Chris@102
|
101 #else
|
Chris@102
|
102 template<class A>
|
Chris@102
|
103 explicit aligned_allocator_adaptor(const A& alloc)
|
Chris@102
|
104 BOOST_NOEXCEPT
|
Chris@102
|
105 : Allocator(alloc) {
|
Chris@102
|
106 }
|
Chris@102
|
107 #endif
|
Chris@102
|
108
|
Chris@102
|
109 template<class U>
|
Chris@102
|
110 aligned_allocator_adaptor(const
|
Chris@102
|
111 aligned_allocator_adaptor<U, Alignment>& other)
|
Chris@102
|
112 BOOST_NOEXCEPT
|
Chris@102
|
113 : Allocator(other.base()) {
|
Chris@102
|
114 }
|
Chris@102
|
115
|
Chris@102
|
116 Allocator& base()
|
Chris@102
|
117 BOOST_NOEXCEPT {
|
Chris@102
|
118 return static_cast<Allocator&>(*this);
|
Chris@102
|
119 }
|
Chris@102
|
120
|
Chris@102
|
121 const Allocator& base() const
|
Chris@102
|
122 BOOST_NOEXCEPT {
|
Chris@102
|
123 return static_cast<const Allocator&>(*this);
|
Chris@102
|
124 }
|
Chris@102
|
125
|
Chris@102
|
126 pointer allocate(size_type size) {
|
Chris@102
|
127 std::size_t n1 = size * sizeof(value_type);
|
Chris@102
|
128 std::size_t n2 = n1 + MaxAlign::value - 1;
|
Chris@102
|
129 CharAlloc a(base());
|
Chris@102
|
130 CharPtr p1 = a.allocate(sizeof p1 + n2);
|
Chris@102
|
131 void* p2 = detail::addressof(*p1) + sizeof p1;
|
Chris@102
|
132 (void)align(MaxAlign::value, n1, p2, n2);
|
Chris@102
|
133 void* p3 = static_cast<CharPtr*>(p2) - 1;
|
Chris@102
|
134 ::new(p3) CharPtr(p1);
|
Chris@102
|
135 return static_cast<pointer>(p2);
|
Chris@102
|
136 }
|
Chris@102
|
137
|
Chris@102
|
138 pointer allocate(size_type size, const_void_pointer hint) {
|
Chris@102
|
139 std::size_t n1 = size * sizeof(value_type);
|
Chris@102
|
140 std::size_t n2 = n1 + MaxAlign::value - 1;
|
Chris@102
|
141 CharPtr h = CharPtr();
|
Chris@102
|
142 if (hint) {
|
Chris@102
|
143 h = *(static_cast<const CharPtr*>(hint) - 1);
|
Chris@102
|
144 }
|
Chris@102
|
145 CharAlloc a(base());
|
Chris@102
|
146 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
Chris@102
|
147 CharPtr p1 = CharTraits::allocate(a, sizeof p1 +
|
Chris@102
|
148 n2, h);
|
Chris@102
|
149 #else
|
Chris@102
|
150 CharPtr p1 = a.allocate(sizeof p1 + n2, h);
|
Chris@102
|
151 #endif
|
Chris@102
|
152 void* p2 = detail::addressof(*p1) + sizeof p1;
|
Chris@102
|
153 (void)align(MaxAlign::value, n1, p2, n2);
|
Chris@102
|
154 void* p3 = static_cast<CharPtr*>(p2) - 1;
|
Chris@102
|
155 ::new(p3) CharPtr(p1);
|
Chris@102
|
156 return static_cast<pointer>(p2);
|
Chris@102
|
157 }
|
Chris@102
|
158
|
Chris@102
|
159 void deallocate(pointer ptr, size_type size) {
|
Chris@102
|
160 CharPtr* p1 = reinterpret_cast<CharPtr*>(ptr) - 1;
|
Chris@102
|
161 CharPtr p2 = *p1;
|
Chris@102
|
162 p1->~CharPtr();
|
Chris@102
|
163 CharAlloc a(base());
|
Chris@102
|
164 a.deallocate(p2, size * sizeof(value_type) +
|
Chris@102
|
165 MaxAlign::value + sizeof p2);
|
Chris@102
|
166 }
|
Chris@102
|
167 };
|
Chris@102
|
168
|
Chris@102
|
169 template<class A1, class A2, std::size_t Alignment>
|
Chris@102
|
170 inline bool operator==(const aligned_allocator_adaptor<A1,
|
Chris@102
|
171 Alignment>& a, const aligned_allocator_adaptor<A2,
|
Chris@102
|
172 Alignment>& b) BOOST_NOEXCEPT
|
Chris@102
|
173 {
|
Chris@102
|
174 return a.base() == b.base();
|
Chris@102
|
175 }
|
Chris@102
|
176
|
Chris@102
|
177 template<class A1, class A2, std::size_t Alignment>
|
Chris@102
|
178 inline bool operator!=(const aligned_allocator_adaptor<A1,
|
Chris@102
|
179 Alignment>& a, const aligned_allocator_adaptor<A2,
|
Chris@102
|
180 Alignment>& b) BOOST_NOEXCEPT
|
Chris@102
|
181 {
|
Chris@102
|
182 return !(a == b);
|
Chris@102
|
183 }
|
Chris@102
|
184 }
|
Chris@102
|
185 }
|
Chris@102
|
186
|
Chris@102
|
187 #endif
|