123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /*
- Copyright 2014-2016 Glen Joseph Fernandes
- ([email protected])
- Distributed under the Boost Software License, Version 1.0.
- (http://www.boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
- #define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP
- #include <boost/align/detail/is_alignment_constant.hpp>
- #include <boost/align/detail/max_align.hpp>
- #include <boost/align/detail/max_size.hpp>
- #include <boost/align/align.hpp>
- #include <boost/align/aligned_allocator_adaptor_forward.hpp>
- #include <boost/align/alignment_of.hpp>
- #include <boost/core/pointer_traits.hpp>
- #include <boost/static_assert.hpp>
- #include <new>
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- #include <memory>
- #endif
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- #include <utility>
- #endif
- namespace boost {
- namespace alignment {
- template<class Allocator, std::size_t Alignment>
- class aligned_allocator_adaptor
- : public Allocator {
- BOOST_STATIC_ASSERT(detail::is_alignment_constant<Alignment>::value);
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef std::allocator_traits<Allocator> traits;
- typedef typename traits::template rebind_alloc<char> char_alloc;
- typedef typename traits::template rebind_traits<char> char_traits;
- typedef typename char_traits::pointer char_ptr;
- #else
- typedef typename Allocator::template rebind<char>::other char_alloc;
- typedef typename char_alloc::pointer char_ptr;
- #endif
- public:
- typedef typename Allocator::value_type value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef void* void_pointer;
- typedef const void* const_void_pointer;
- typedef std::size_t size_type;
- typedef std::ptrdiff_t difference_type;
- private:
- template<class U>
- struct min_align {
- enum {
- value = detail::max_size<Alignment,
- detail::max_align<U, char_ptr>::value>::value
- };
- };
- public:
- template<class U>
- struct rebind {
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- typedef aligned_allocator_adaptor<typename traits::template
- rebind_alloc<U>, Alignment> other;
- #else
- typedef aligned_allocator_adaptor<typename Allocator::template
- rebind<U>::other, Alignment> other;
- #endif
- };
- aligned_allocator_adaptor()
- : Allocator() { }
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- template<class A>
- explicit aligned_allocator_adaptor(A&& alloc) BOOST_NOEXCEPT
- : Allocator(std::forward<A>(alloc)) { }
- #else
- template<class A>
- explicit aligned_allocator_adaptor(const A& alloc) BOOST_NOEXCEPT
- : Allocator(alloc) { }
- #endif
- template<class U>
- aligned_allocator_adaptor(const aligned_allocator_adaptor<U,
- Alignment>& other) BOOST_NOEXCEPT
- : Allocator(other.base()) { }
- Allocator& base() BOOST_NOEXCEPT {
- return static_cast<Allocator&>(*this);
- }
- const Allocator& base() const BOOST_NOEXCEPT {
- return static_cast<const Allocator&>(*this);
- }
- pointer allocate(size_type size) {
- enum {
- m = min_align<value_type>::value
- };
- std::size_t s = size * sizeof(value_type);
- std::size_t n = s + m - 1;
- char_alloc a(base());
- char_ptr p = a.allocate(sizeof p + n);
- void* r = boost::to_address(p) + sizeof p;
- (void)boost::alignment::align(m, s, r, n);
- ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p);
- return static_cast<pointer>(r);
- }
- pointer allocate(size_type size, const_void_pointer hint) {
- enum {
- m = min_align<value_type>::value
- };
- std::size_t s = size * sizeof(value_type);
- std::size_t n = s + m - 1;
- char_ptr h = char_ptr();
- if (hint) {
- h = *(static_cast<const char_ptr*>(hint) - 1);
- }
- char_alloc a(base());
- #if !defined(BOOST_NO_CXX11_ALLOCATOR)
- char_ptr p = char_traits::allocate(a, sizeof p + n, h);
- #else
- char_ptr p = a.allocate(sizeof p + n, h);
- #endif
- void* r = boost::to_address(p) + sizeof p;
- (void)boost::alignment::align(m, s, r, n);
- ::new(static_cast<void*>(static_cast<char_ptr*>(r) - 1)) char_ptr(p);
- return static_cast<pointer>(r);
- }
- void deallocate(pointer ptr, size_type size) {
- enum {
- m = min_align<value_type>::value
- };
- char_ptr* p = reinterpret_cast<char_ptr*>(ptr) - 1;
- char_ptr r = *p;
- p->~char_ptr();
- char_alloc a(base());
- a.deallocate(r, sizeof r + size * sizeof(value_type) + m - 1);
- }
- };
- template<class A, class B, std::size_t Alignment>
- inline bool
- operator==(const aligned_allocator_adaptor<A, Alignment>& a,
- const aligned_allocator_adaptor<B, Alignment>& b) BOOST_NOEXCEPT
- {
- return a.base() == b.base();
- }
- template<class A, class B, std::size_t Alignment>
- inline bool
- operator!=(const aligned_allocator_adaptor<A, Alignment>& a,
- const aligned_allocator_adaptor<B, Alignment>& b) BOOST_NOEXCEPT
- {
- return !(a == b);
- }
- } /* alignment */
- } /* boost */
- #endif
|