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