resource_adaptor.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
  11. #define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
  12. #if defined (_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include <boost/config.hpp>
  16. #include <boost/container/pmr/memory_resource.hpp>
  17. #include <boost/container/allocator_traits.hpp>
  18. #include <boost/intrusive/detail/ebo_functor_holder.hpp>
  19. #include <boost/move/utility_core.hpp>
  20. namespace boost {
  21. namespace container {
  22. namespace pmr {
  23. //! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
  24. //! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
  25. //! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
  26. //! an alias to this class template such that Allocator is rebound to a char value type in every
  27. //! specialization of the class template. The requirements on this class template are defined below.
  28. //! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
  29. //! the following additional requirements:
  30. //!
  31. //! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
  32. //! `typename allocator_traits<Allocator>:: value_type*`.
  33. //!
  34. //! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
  35. //! `typename allocator_traits<Allocator>:: value_type const*`.
  36. //!
  37. //! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
  38. //!
  39. //! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
  40. template <class Allocator>
  41. class resource_adaptor_imp
  42. : public memory_resource
  43. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  44. , private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
  45. #endif
  46. {
  47. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  48. Allocator m_alloc;
  49. #else
  50. BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
  51. typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
  52. void static_assert_if_not_char_allocator() const
  53. {
  54. //This class can only be used with allocators type char
  55. BOOST_STATIC_ASSERT((dtl::is_same<typename Allocator::value_type, char>::value));
  56. }
  57. #endif
  58. public:
  59. typedef Allocator allocator_type;
  60. //! <b>Effects</b>: Default constructs
  61. //! m_alloc.
  62. resource_adaptor_imp()
  63. { this->static_assert_if_not_char_allocator(); }
  64. //! <b>Effects</b>: Copy constructs
  65. //! m_alloc.
  66. resource_adaptor_imp(const resource_adaptor_imp &other)
  67. : ebo_alloc_t(other.ebo_alloc_t::get())
  68. {}
  69. //! <b>Effects</b>: Move constructs
  70. //! m_alloc.
  71. resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
  72. : ebo_alloc_t(::boost::move(other.get()))
  73. {}
  74. //! <b>Effects</b>: Initializes m_alloc with
  75. //! a2.
  76. explicit resource_adaptor_imp(const Allocator& a2)
  77. : ebo_alloc_t(a2)
  78. { this->static_assert_if_not_char_allocator(); }
  79. //! <b>Effects</b>: Initializes m_alloc with
  80. //! a2.
  81. explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
  82. : ebo_alloc_t(::boost::move(a2))
  83. { this->static_assert_if_not_char_allocator(); }
  84. //! <b>Effects</b>: Copy assigns
  85. //! m_alloc.
  86. resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
  87. { this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this; }
  88. //! <b>Effects</b>: Move assigns
  89. //! m_alloc.
  90. resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
  91. { this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this; }
  92. //! <b>Effects</b>: Returns m_alloc.
  93. allocator_type &get_allocator()
  94. { return this->ebo_alloc_t::get(); }
  95. //! <b>Effects</b>: Returns m_alloc.
  96. const allocator_type &get_allocator() const
  97. { return this->ebo_alloc_t::get(); }
  98. protected:
  99. //! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
  100. //! of the allocated memory shall meet the requirements for a class derived from memory_resource.
  101. virtual void* do_allocate(size_t bytes, size_t alignment)
  102. { (void)alignment; return this->ebo_alloc_t::get().allocate(bytes); }
  103. //! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
  104. //! subsequently deallocated.
  105. //!
  106. //! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
  107. virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
  108. { (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes); }
  109. //! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
  110. //!
  111. //! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
  112. virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
  113. {
  114. const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
  115. return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
  116. }
  117. };
  118. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  119. //! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
  120. //! such that Allocator is rebound to a char value type.
  121. template <class Allocator>
  122. using resource_adaptor = resource_adaptor_imp
  123. <typename allocator_traits<Allocator>::template rebind_alloc<char> >;
  124. #else
  125. template <class Allocator>
  126. class resource_adaptor
  127. : public resource_adaptor_imp
  128. <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
  129. {
  130. typedef resource_adaptor_imp
  131. <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
  132. BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
  133. public:
  134. resource_adaptor()
  135. : base_t()
  136. {}
  137. resource_adaptor(const resource_adaptor &other)
  138. : base_t(other)
  139. {}
  140. resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
  141. : base_t(BOOST_MOVE_BASE(base_t, other))
  142. {}
  143. explicit resource_adaptor(const Allocator& a2)
  144. : base_t(a2)
  145. {}
  146. explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
  147. : base_t(::boost::move(a2))
  148. {}
  149. resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
  150. { return static_cast<resource_adaptor&>(this->base_t::operator=(other)); }
  151. resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
  152. { return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other))); }
  153. //get_allocator and protected functions are properly inherited
  154. };
  155. #endif
  156. } //namespace pmr {
  157. } //namespace container {
  158. } //namespace boost {
  159. #endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP