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