]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/container/pmr/resource_adaptor.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / container / pmr / resource_adaptor.hpp
index f5ce5c8a18d108d3f6d33824ff415c75f6d27d75..321635054221ffd2f8c8740ed650b0949eac0089 100644 (file)
 #  pragma once 
 #endif
 
-#include <boost/config.hpp>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
 #include <boost/container/pmr/memory_resource.hpp>
 #include <boost/container/allocator_traits.hpp>
 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
 #include <boost/move/utility_core.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/container/detail/std_fwd.hpp>
+
+#include <cstring>
 
 namespace boost {
 namespace container {
+
+namespace pmr_dtl {
+
+template<class T>
+struct max_allocator_alignment
+{
+   static const std::size_t value = 1;
+};
+
+template<class T>
+struct max_allocator_alignment< ::boost::container::new_allocator<T> >
+{
+   static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+};
+
+template<class T>
+struct max_allocator_alignment< std::allocator<T> >
+{
+   static const std::size_t value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+};
+
+}  //namespace pmr_dtl
+
 namespace pmr {
 
 //! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
@@ -57,7 +87,7 @@ class resource_adaptor_imp
    void static_assert_if_not_char_allocator() const
    {
       //This class can only be used with allocators type char
-      BOOST_STATIC_ASSERT((dtl::is_same<typename Allocator::value_type, char>::value));
+      BOOST_STATIC_ASSERT((boost::container::dtl::is_same<typename Allocator::value_type, char>::value));
    }
    #endif
 
@@ -114,15 +144,25 @@ class resource_adaptor_imp
    protected:
    //! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
    //!   of the allocated memory shall meet the requirements for a class derived from memory_resource.
-   virtual void* do_allocate(size_t bytes, size_t alignment)
-   {  (void)alignment;  return this->ebo_alloc_t::get().allocate(bytes);  }
+   virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+   {
+      if (alignment <= priv_guaranteed_allocator_alignment())
+         return this->ebo_alloc_t::get().allocate(bytes);
+      else
+         return this->priv_aligned_alloc(bytes, alignment);
+   }
 
    //! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
    //!   subsequently deallocated. 
    //!
    //! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
-   virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
-   {  (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes);   }
+   virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+   {
+      if (alignment <= priv_guaranteed_allocator_alignment())
+         this->ebo_alloc_t::get().deallocate((char*)p, bytes);
+      else
+         this->priv_aligned_dealloc(p, bytes, alignment);
+   }
 
    //! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
    //!
@@ -132,6 +172,48 @@ class resource_adaptor_imp
       const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
       return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
    }
+
+   private:
+   void * priv_aligned_alloc(std::size_t bytes, std::size_t alignment)
+   {
+      //Allocate space for requested bytes, plus alignment, plus bookeeping data
+      void *const p = this->ebo_alloc_t::get().allocate(bytes + priv_extra_bytes_for_overalignment(alignment));
+
+      if (0 != p) {
+         //Obtain the aligned address after the bookeeping data
+         void *const aligned_ptr = (void*)(((std::size_t)p + priv_extra_bytes_for_overalignment(alignment)) & ~(alignment - 1));
+
+         //Store bookeeping data. Use memcpy as the underlying memory might be unaligned for
+         //a pointer (e.g. 2 byte alignment in 32 bit, 4 byte alignment in 64 bit)
+         std::memcpy(priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), &p, sizeof(p));
+         return aligned_ptr;
+      }
+      return 0;
+   }
+
+   void priv_aligned_dealloc(void *aligned_ptr, std::size_t bytes, std::size_t alignment)
+   {
+      //Obtain bookeeping data
+      void *p;
+      std::memcpy(&p, priv_bookeeping_addr_from_aligned_ptr(aligned_ptr), sizeof(p));
+      std::size_t s  = bytes + priv_extra_bytes_for_overalignment(alignment);
+      this->ebo_alloc_t::get().deallocate((char*)p, s);
+   }
+
+   static BOOST_CONTAINER_FORCEINLINE void *priv_bookeeping_addr_from_aligned_ptr(void *aligned_ptr)
+   {
+      return reinterpret_cast<void*>(reinterpret_cast<std::size_t>(aligned_ptr) - sizeof(void*));
+   }
+
+   BOOST_CONTAINER_FORCEINLINE static std::size_t priv_extra_bytes_for_overalignment(std::size_t alignment)
+   {
+      return alignment - 1 + sizeof(void*);
+   }
+
+   BOOST_CONTAINER_FORCEINLINE static std::size_t priv_guaranteed_allocator_alignment()
+   {
+      return pmr_dtl::max_allocator_alignment<Allocator>::value;
+   }
 };
 
 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -172,7 +254,7 @@ class resource_adaptor
    {}
 
    explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
-      : base_t(BOOST_MOVE_BASE(base_t, a2))
+      : base_t(::boost::move(a2))
    {}
 
    resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
@@ -190,4 +272,6 @@ class resource_adaptor
 }  //namespace container {
 }  //namespace boost {
 
+#include <boost/container/detail/config_end.hpp>
+
 #endif   //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP