2 * Copyright (c) 2012-2014 Glen Joseph Fernandes
3 * glenfe at live dot com
5 * Distributed under the Boost Software License,
6 * Version 1.0. (See accompanying file LICENSE_1_0.txt
7 * or copy at http://boost.org/LICENSE_1_0.txt)
9 #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
10 #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
12 #include <boost/align/align.hpp>
13 #include <boost/smart_ptr/detail/array_traits.hpp>
14 #include <boost/smart_ptr/detail/array_utility.hpp>
15 #include <boost/type_traits/alignment_of.hpp>
19 struct ms_init_tag { };
20 struct ms_noinit_tag { };
23 struct ms_allocator_state;
26 struct ms_allocator_state<T[]> {
27 typedef typename array_base<T>::type type;
29 ms_allocator_state(std::size_t size_,
31 : size(size_ * array_total<T>::size),
43 template<class T, std::size_t N>
44 struct ms_allocator_state<T[N]> {
45 typedef typename array_base<T>::type type;
47 ms_allocator_state(type** result_)
52 size = array_total<T[N]>::size
61 template<class A, class T, class R>
64 template<class A_, class T_, class R_>
65 friend class as_allocator;
67 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
68 typedef std::allocator_traits<A> AT;
69 typedef typename AT::template rebind_alloc<char> CA;
70 typedef typename AT::template rebind_traits<char> CT;
72 typedef typename A::template rebind<char>::other CA;
76 typedef A allocator_type;
78 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
79 typedef typename AT::value_type value_type;
80 typedef typename AT::pointer pointer;
81 typedef typename AT::const_pointer const_pointer;
82 typedef typename AT::void_pointer void_pointer;
83 typedef typename AT::const_void_pointer const_void_pointer;
84 typedef typename AT::size_type size_type;
85 typedef typename AT::difference_type difference_type;
87 typedef typename A::value_type value_type;
88 typedef typename A::pointer pointer;
89 typedef typename A::const_pointer const_pointer;
90 typedef typename A::size_type size_type;
91 typedef typename A::difference_type difference_type;
92 typedef typename A::reference reference;
93 typedef typename A::const_reference const_reference;
94 typedef void* void_pointer;
95 typedef const void* const_void_pointer;
100 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
101 typedef as_allocator<typename AT::
102 template rebind_alloc<U>, T, R> other;
104 typedef as_allocator<typename A::
105 template rebind<U>::other, T, R> other;
109 typedef typename array_base<T>::type type;
111 as_allocator(const A& allocator_, type** result)
116 as_allocator(const A& allocator_, std::size_t size,
123 as_allocator(const as_allocator<U, T, R>& other)
124 : A(other.allocator()),
128 pointer allocate(size_type count, const_void_pointer = 0) {
130 M = boost::alignment_of<type>::value
132 std::size_t n1 = count * sizeof(value_type);
133 std::size_t n2 = data.size * sizeof(type);
134 std::size_t n3 = n2 + M;
136 void* p1 = ca.allocate(n1 + n3);
137 void* p2 = static_cast<char*>(p1) + n1;
138 (void)boost::alignment::align(M, n2, p2, n3);
139 *data.result = static_cast<type*>(p2);
140 return static_cast<value_type*>(p1);
143 void deallocate(pointer memory, size_type count) {
145 M = boost::alignment_of<type>::value
147 std::size_t n1 = count * sizeof(value_type);
148 std::size_t n2 = data.size * sizeof(type) + M;
149 char* p1 = reinterpret_cast<char*>(memory);
151 ca.deallocate(p1, n1 + n2);
154 const A& allocator() const {
155 return static_cast<const A&>(*this);
159 return static_cast<A&>(*this);
162 void set(type* memory) {
163 data.object = memory;
174 void release(ms_init_tag) {
175 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
176 as_destroy(allocator(), data.object, data.size);
178 ms_destroy(data.object, data.size);
182 void release(ms_noinit_tag) {
183 ms_destroy(data.object, data.size);
186 ms_allocator_state<T> data;
189 template<class A1, class A2, class T, class R>
190 bool operator==(const as_allocator<A1, T, R>& a1,
191 const as_allocator<A2, T, R>& a2) {
192 return a1.allocator() == a2.allocator();
195 template<class A1, class A2, class T, class R>
196 bool operator!=(const as_allocator<A1, T, R>& a1,
197 const as_allocator<A2, T, R>& a2) {
198 return a1.allocator() != a2.allocator();
201 template<class T, class Y = char>
204 template<class T, class Y>
206 template<class T_, class Y_>
207 friend class ms_allocator;
210 typedef typename array_base<T>::type type;
212 typedef Y value_type;
214 typedef const Y* const_pointer;
215 typedef std::size_t size_type;
216 typedef std::ptrdiff_t difference_type;
217 typedef Y& reference;
218 typedef const Y& const_reference;
222 typedef ms_allocator<T, U> other;
225 ms_allocator(type** result)
229 ms_allocator(std::size_t size, type** result)
230 : data(size, result) {
234 ms_allocator(const ms_allocator<T, U>& other)
238 pointer allocate(size_type count, const void* = 0) {
240 M = boost::alignment_of<type>::value
242 std::size_t n1 = count * sizeof(Y);
243 std::size_t n2 = data.size * sizeof(type);
244 std::size_t n3 = n2 + M;
245 void* p1 = ::operator new(n1 + n3);
246 void* p2 = static_cast<char*>(p1) + n1;
247 (void)boost::alignment::align(M, n2, p2, n3);
248 *data.result = static_cast<type*>(p2);
249 return static_cast<Y*>(p1);
252 void deallocate(pointer memory, size_type) {
254 ::operator delete(p1);
257 #if defined(BOOST_NO_CXX11_ALLOCATOR)
258 pointer address(reference value) const {
262 const_pointer address(const_reference value) const {
266 size_type max_size() const {
268 N = static_cast<std::size_t>(-1) / sizeof(Y)
273 void construct(pointer memory, const_reference value) {
278 void destroy(pointer memory) {
284 void set(type* memory) {
285 data.object = memory;
290 ms_destroy(data.object, data.size);
295 ms_allocator_state<T> data;
298 template<class T, class Y1, class Y2>
299 bool operator==(const ms_allocator<T, Y1>&,
300 const ms_allocator<T, Y2>&) {
304 template<class T, class Y1, class Y2>
305 bool operator!=(const ms_allocator<T, Y1>&,
306 const ms_allocator<T, Y2>&) {
310 class ms_in_allocator_tag {
312 void operator()(const void*) {