Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:34:56

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
0012 #define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
0013 
0014 #if defined (_MSC_VER)
0015 #  pragma once 
0016 #endif
0017 
0018 #include <boost/container/detail/config_begin.hpp>
0019 #include <boost/container/detail/workaround.hpp>
0020 #include <boost/container/container_fwd.hpp>
0021 
0022 #include <boost/container/pmr/memory_resource.hpp>
0023 #include <boost/container/allocator_traits.hpp>
0024 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
0025 #include <boost/move/utility_core.hpp>
0026 #include <boost/move/detail/type_traits.hpp>
0027 #include <boost/container/detail/std_fwd.hpp>
0028 
0029 #include <cstring>
0030 
0031 namespace boost {
0032 namespace container {
0033 
0034 namespace pmr_dtl {
0035 
0036 template<class T>
0037 struct max_allocator_alignment
0038 {
0039    static const std::size_t value = 1;
0040 };
0041 
0042 template<class T>
0043 struct max_allocator_alignment< ::boost::container::new_allocator<T> >
0044 {
0045    static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
0046 };
0047 
0048 template<class T>
0049 struct max_allocator_alignment< std::allocator<T> >
0050 {
0051    static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
0052 };
0053 
0054 }  //namespace pmr_dtl
0055 
0056 namespace pmr {
0057 
0058 //! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
0059 //! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
0060 //! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
0061 //! an alias to this class template such that Allocator is rebound to a char value type in every
0062 //! specialization of the class template. The requirements on this class template are defined below.
0063 //! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
0064 //! the following additional requirements:
0065 //!
0066 //! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
0067 //!   `typename allocator_traits<Allocator>:: value_type*`.
0068 //!
0069 //! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
0070 //!   `typename allocator_traits<Allocator>:: value_type const*`.
0071 //!
0072 //! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
0073 //!
0074 //! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
0075 template <class Allocator>
0076 class resource_adaptor_imp
0077    : public  memory_resource
0078    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0079    , private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
0080    #endif
0081 {
0082    #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0083    Allocator m_alloc;
0084    #else
0085    BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
0086    typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
0087    void static_assert_if_not_char_allocator() const
0088    {
0089       //This class can only be used with allocators type char
0090       BOOST_STATIC_ASSERT((boost::container::dtl::is_same<typename Allocator::value_type, char>::value));
0091    }
0092    #endif
0093 
0094    public:
0095    typedef Allocator allocator_type;
0096 
0097    //! <b>Effects</b>: Default constructs
0098    //!   m_alloc.
0099    resource_adaptor_imp()
0100    {  this->static_assert_if_not_char_allocator(); }
0101 
0102    //! <b>Effects</b>: Copy constructs
0103    //!   m_alloc.
0104    resource_adaptor_imp(const resource_adaptor_imp &other)
0105       : ebo_alloc_t(other.ebo_alloc_t::get())
0106    {}
0107 
0108    //! <b>Effects</b>: Move constructs
0109    //!   m_alloc.
0110    resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
0111       : ebo_alloc_t(::boost::move(other.get()))
0112    {}
0113 
0114    //! <b>Effects</b>: Initializes m_alloc with
0115    //!   a2.
0116    explicit resource_adaptor_imp(const Allocator& a2)
0117       : ebo_alloc_t(a2)
0118    {  this->static_assert_if_not_char_allocator(); }
0119 
0120    //! <b>Effects</b>: Initializes m_alloc with
0121    //!   a2.
0122    explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
0123       : ebo_alloc_t(::boost::move(a2))
0124    {  this->static_assert_if_not_char_allocator(); }
0125 
0126    //! <b>Effects</b>: Copy assigns
0127    //!   m_alloc.
0128    resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
0129    {  this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this;  }
0130 
0131    //! <b>Effects</b>: Move assigns
0132    //!   m_alloc.
0133    resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
0134    {  this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this;  }
0135 
0136    //! <b>Effects</b>: Returns m_alloc.
0137    allocator_type &get_allocator()
0138    {  return this->ebo_alloc_t::get(); }
0139 
0140    //! <b>Effects</b>: Returns m_alloc.
0141    const allocator_type &get_allocator() const
0142    {  return this->ebo_alloc_t::get(); }
0143 
0144    protected:
0145    //! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
0146    //!   of the allocated memory shall meet the requirements for a class derived from memory_resource.
0147    virtual void* do_allocate(std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
0148    {
0149       if (alignment <= priv_guaranteed_allocator_alignment())
0150          return this->ebo_alloc_t::get().allocate(bytes);
0151       else
0152          return this->priv_aligned_alloc(bytes, alignment);
0153    }
0154 
0155    //! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
0156    //!   subsequently deallocated. 
0157    //!
0158    //! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
0159    virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_OVERRIDE
0160    {
0161       if (alignment <= priv_guaranteed_allocator_alignment())
0162          this->ebo_alloc_t::get().deallocate((char*)p, bytes);
0163       else
0164          this->priv_aligned_dealloc(p, bytes, alignment);
0165    }
0166 
0167    //! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
0168    //!
0169    //! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
0170    virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT BOOST_OVERRIDE
0171    {
0172       const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
0173       return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
0174    }
0175 
0176    private:
0177    void * priv_aligned_alloc(std::size_t bytes, std::size_t alignment)
0178    {
0179       //Allocate space for requested bytes, plus alignment, plus bookeeping data
0180       void *const p = this->ebo_alloc_t::get().allocate(bytes + priv_extra_bytes_for_overalignment(alignment));
0181 
0182       if (0 != p) {
0183          //Obtain the aligned address after the bookeeping data
0184          void *const aligned_ptr = (void*)(((std::size_t)p + priv_extra_bytes_for_overalignment(alignment)) & ~(alignment - 1));
0185 
0186          //Store bookeeping data. Use memcpy as the underlying memory might be unaligned for
0187          //a pointer (e.g. 2 byte alignment in 32 bit, 4 byte alignment in 64 bit)
0188          std::memcpy(priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), &p, sizeof(p));
0189          return aligned_ptr;
0190       }
0191       return 0;
0192    }
0193 
0194    void priv_aligned_dealloc(void *aligned_ptr, std::size_t bytes, std::size_t alignment)
0195    {
0196       //Obtain bookeeping data
0197       void *p;
0198       std::memcpy(&p, priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), sizeof(p));
0199       std::size_t s  = bytes + priv_extra_bytes_for_overalignment(alignment);
0200       this->ebo_alloc_t::get().deallocate((char*)p, s);
0201    }
0202 
0203    static BOOST_CONTAINER_FORCEINLINE void *priv_bookeeping_addr_from_aligned_ptr(void *aligned_ptr)
0204    {
0205       return reinterpret_cast<void*>(reinterpret_cast<std::size_t>(aligned_ptr) - sizeof(void*));
0206    }
0207 
0208    BOOST_CONTAINER_FORCEINLINE static std::size_t priv_extra_bytes_for_overalignment(std::size_t alignment)
0209    {
0210       return alignment - 1 + sizeof(void*);
0211    }
0212 
0213    BOOST_CONTAINER_FORCEINLINE static std::size_t priv_guaranteed_allocator_alignment()
0214    {
0215       return pmr_dtl::max_allocator_alignment<Allocator>::value;
0216    }
0217 };
0218 
0219 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
0220 
0221 //! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
0222 //! such that Allocator is rebound to a char value type.
0223 template <class Allocator>
0224 using resource_adaptor = resource_adaptor_imp
0225    <typename allocator_traits<Allocator>::template rebind_alloc<char> >;
0226 
0227 #else
0228 
0229 template <class Allocator>
0230 class resource_adaptor
0231    : public resource_adaptor_imp
0232       <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
0233 {
0234    typedef resource_adaptor_imp
0235       <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
0236 
0237    BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
0238 
0239    public:
0240    resource_adaptor()
0241       : base_t()
0242    {}
0243 
0244    resource_adaptor(const resource_adaptor &other)
0245       : base_t(other)
0246    {}
0247 
0248    resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
0249       : base_t(BOOST_MOVE_BASE(base_t, other))
0250    {}
0251 
0252    explicit resource_adaptor(const Allocator& a2)
0253       : base_t(a2)
0254    {}
0255 
0256    explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
0257       : base_t(::boost::move(a2))
0258    {}
0259 
0260    resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
0261    {  return static_cast<resource_adaptor&>(this->base_t::operator=(other));  }
0262 
0263    resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
0264    {  return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other)));  }
0265 
0266    //get_allocator and protected functions are properly inherited
0267 };
0268 
0269 #endif
0270 
0271 }  //namespace pmr {
0272 }  //namespace container {
0273 }  //namespace boost {
0274 
0275 #include <boost/container/detail/config_end.hpp>
0276 
0277 #endif   //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP