aligned_allocator_adaptor.hpp 5.1 KB

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