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