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