1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
#define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
#include <__assert>
#include <__config>
#include <__memory_resource/memory_resource.h>
#include <__utility/exception_guard.h>
#include <cstddef>
#include <limits>
#include <new>
#include <stdexcept>
#include <tuple>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
#if _LIBCPP_STD_VER > 14
_LIBCPP_BEGIN_NAMESPACE_STD
namespace pmr {
// [mem.poly.allocator.class]
template <class _ValueType
# if _LIBCPP_STD_VER >= 20
= byte
# endif
>
class _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
public:
using value_type = _ValueType;
// [mem.poly.allocator.ctor]
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator() noexcept : __res_(std::pmr::get_default_resource()) {}
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {}
polymorphic_allocator(const polymorphic_allocator&) = default;
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept
: __res_(__other.resource()) {}
polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;
// [mem.poly.allocator.mem]
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) {
if (__n > __max_size()) {
__throw_bad_array_new_length();
}
return static_cast<_ValueType*>(__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType)));
}
_LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) {
_LIBCPP_ASSERT(__n <= __max_size(), "deallocate called for size which exceeds max_size()");
__res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
}
# if _LIBCPP_STD_VER >= 20
[[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] void*
allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
return __res_->allocate(__nbytes, __alignment);
}
void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
__res_->deallocate(__ptr, __nbytes, __alignment);
}
template <class _Type>
[[nodiscard]] _Type* allocate_object(size_t __n = 1) {
if (numeric_limits<size_t>::max() / sizeof(_Type) < __n)
std::__throw_bad_array_new_length();
return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type)));
}
template <class _Type>
void deallocate_object(_Type* __ptr, size_t __n = 1) {
deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type));
}
template <class _Type, class... _CtorArgs>
[[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) {
_Type* __ptr = allocate_object<_Type>();
auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });
construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);
__guard.__complete();
return __ptr;
}
template <class _Type>
void delete_object(_Type* __ptr) {
destroy(__ptr);
deallocate_object(__ptr);
}
# endif // _LIBCPP_STD_VER >= 20
template <class _Tp, class... _Ts>
_LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) {
std::__user_alloc_construct_impl(
typename __uses_alloc_ctor<_Tp, polymorphic_allocator&, _Ts...>::type(),
__p,
*this,
std::forward<_Ts>(__args)...);
}
template <class _T1, class _T2, class... _Args1, class... _Args2>
_LIBCPP_HIDE_FROM_ABI void
construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) {
::new ((void*)__p) pair<_T1, _T2>(
piecewise_construct,
__transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(),
std::move(__x),
typename __make_tuple_indices<sizeof...(_Args1)>::type{}),
__transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(),
std::move(__y),
typename __make_tuple_indices<sizeof...(_Args2)>::type{}));
}
template <class _T1, class _T2>
_LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) {
construct(__p, piecewise_construct, tuple<>(), tuple<>());
}
template <class _T1, class _T2, class _Up, class _Vp>
_LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) {
construct(__p,
piecewise_construct,
std::forward_as_tuple(std::forward<_Up>(__u)),
std::forward_as_tuple(std::forward<_Vp>(__v)));
}
template <class _T1, class _T2, class _U1, class _U2>
_LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_U1, _U2>& __pr) {
construct(__p, piecewise_construct, std::forward_as_tuple(__pr.first), std::forward_as_tuple(__pr.second));
}
template <class _T1, class _T2, class _U1, class _U2>
_LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_U1, _U2>&& __pr) {
construct(__p,
piecewise_construct,
std::forward_as_tuple(std::forward<_U1>(__pr.first)),
std::forward_as_tuple(std::forward<_U2>(__pr.second)));
}
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) {
__p->~_Tp();
}
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator select_on_container_copy_construction() const noexcept {
return polymorphic_allocator();
}
_LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }
private:
template <class... _Args, size_t... _Is>
_LIBCPP_HIDE_FROM_ABI tuple<_Args&&...>
__transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
return std::forward_as_tuple(std::get<_Is>(std::move(__t))...);
}
template <class... _Args, size_t... _Is>
_LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
__transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...);
}
template <class... _Args, size_t... _Is>
_LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&>
__transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
return _Tup(std::get<_Is>(std::move(__t))..., *this);
}
_LIBCPP_HIDE_FROM_ABI size_t __max_size() const noexcept {
return numeric_limits<size_t>::max() / sizeof(value_type);
}
memory_resource* __res_;
};
// [mem.poly.allocator.eq]
template <class _Tp, class _Up>
inline _LIBCPP_HIDE_FROM_ABI bool
operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
return *__lhs.resource() == *__rhs.resource();
}
template <class _Tp, class _Up>
inline _LIBCPP_HIDE_FROM_ABI bool
operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
return !(__lhs == __rhs);
}
} // namespace pmr
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER > 14
_LIBCPP_POP_MACROS
#endif // _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
|