brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.6 KiB · 9a35119 Raw
250 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H10#define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H11 12#include <__assert>13#include <__config>14#include <__cstddef/byte.h>15#include <__cstddef/max_align_t.h>16#include <__fwd/pair.h>17#include <__memory_resource/memory_resource.h>18#include <__new/exceptions.h>19#include <__new/placement_new_delete.h>20#include <__utility/exception_guard.h>21#include <__utility/piecewise_construct.h>22#include <limits>23#include <tuple>24 25#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)26#  pragma GCC system_header27#endif28 29_LIBCPP_PUSH_MACROS30#include <__undef_macros>31 32#if _LIBCPP_STD_VER >= 1733 34_LIBCPP_BEGIN_NAMESPACE_STD35 36namespace pmr {37 38// [mem.poly.allocator.class]39 40template <class _ValueType41#  if _LIBCPP_STD_VER >= 2042          = byte43#  endif44          >45class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator {46 47public:48  using value_type = _ValueType;49 50  // [mem.poly.allocator.ctor]51 52  _LIBCPP_HIDE_FROM_ABI polymorphic_allocator() noexcept : __res_(std::pmr::get_default_resource()) {}53 54  _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* _LIBCPP_DIAGNOSE_NULLPTR __r) noexcept : __res_(__r) {55    _LIBCPP_ASSERT_NON_NULL(__r, "Attempted to pass a nullptr resource to polymorphic_alloator");56  }57 58  _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default;59 60  template <class _Tp>61  _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept62      : __res_(__other.resource()) {}63 64  polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;65 66  // [mem.poly.allocator.mem]67 68  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) {69    if (__n > __max_size()) {70      std::__throw_bad_array_new_length();71    }72    return static_cast<_ValueType*>(__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType)));73  }74 75  _LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) {76    _LIBCPP_ASSERT_VALID_DEALLOCATION(77        __n <= __max_size(),78        "deallocate() called for a size which exceeds max_size(), leading to a memory leak "79        "(the argument will overflow and result in too few objects being deleted)");80    __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));81  }82 83#  if _LIBCPP_STD_VER >= 2084 85  [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void*86  allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) {87    return __res_->allocate(__nbytes, __alignment);88  }89 90  _LIBCPP_HIDE_FROM_ABI void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) {91    __res_->deallocate(__ptr, __nbytes, __alignment);92  }93 94  template <class _Type>95  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* allocate_object(size_t __n = 1) {96    if (numeric_limits<size_t>::max() / sizeof(_Type) < __n)97      std::__throw_bad_array_new_length();98    return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type)));99  }100 101  template <class _Type>102  _LIBCPP_HIDE_FROM_ABI void deallocate_object(_Type* __ptr, size_t __n = 1) {103    deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type));104  }105 106  template <class _Type, class... _CtorArgs>107  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* new_object(_CtorArgs&&... __ctor_args) {108    _Type* __ptr = allocate_object<_Type>();109    auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });110    construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);111    __guard.__complete();112    return __ptr;113  }114 115  template <class _Type>116  _LIBCPP_HIDE_FROM_ABI void delete_object(_Type* __ptr) {117    destroy(__ptr);118    deallocate_object(__ptr);119  }120 121#  endif // _LIBCPP_STD_VER >= 20122 123  template <class _Tp, class... _Ts>124  _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) {125    std::__user_alloc_construct_impl(126        typename __uses_alloc_ctor<_Tp, polymorphic_allocator&, _Ts...>::type(),127        __p,128        *this,129        std::forward<_Ts>(__args)...);130  }131 132  template <class _T1, class _T2, class... _Args1, class... _Args2>133  _LIBCPP_HIDE_FROM_ABI void134  construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) {135    ::new ((void*)__p) pair<_T1, _T2>(136        piecewise_construct,137        __transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(),138                          std::move(__x),139                          make_index_sequence<sizeof...(_Args1)>()),140        __transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(),141                          std::move(__y),142                          make_index_sequence<sizeof...(_Args2)>()));143  }144 145  template <class _T1, class _T2>146  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) {147    construct(__p, piecewise_construct, tuple<>(), tuple<>());148  }149 150  template <class _T1, class _T2, class _Up, class _Vp>151  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) {152    construct(__p,153              piecewise_construct,154              std::forward_as_tuple(std::forward<_Up>(__u)),155              std::forward_as_tuple(std::forward<_Vp>(__v)));156  }157 158  template <class _T1, class _T2, class _U1, class _U2>159  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_U1, _U2>& __pr) {160    construct(__p, piecewise_construct, std::forward_as_tuple(__pr.first), std::forward_as_tuple(__pr.second));161  }162 163  template <class _T1, class _T2, class _U1, class _U2>164  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_U1, _U2>&& __pr) {165    construct(__p,166              piecewise_construct,167              std::forward_as_tuple(std::forward<_U1>(__pr.first)),168              std::forward_as_tuple(std::forward<_U2>(__pr.second)));169  }170 171  template <class _Tp>172  _LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) {173    __p->~_Tp();174  }175 176  _LIBCPP_HIDE_FROM_ABI polymorphic_allocator select_on_container_copy_construction() const noexcept {177    return polymorphic_allocator();178  }179 180  [[__gnu__::__returns_nonnull__]] _LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }181 182  _LIBCPP_HIDE_FROM_ABI friend bool183  operator==(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {184    return *__lhs.resource() == *__rhs.resource();185  }186 187#  if _LIBCPP_STD_VER <= 17188  // This overload is not specified, it was added due to LWG3683.189  _LIBCPP_HIDE_FROM_ABI friend bool190  operator!=(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {191    return *__lhs.resource() != *__rhs.resource();192  }193#  endif194 195private:196  template <class... _Args, size_t... _Is>197  _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...>198  __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, index_sequence<_Is...>) {199    return std::forward_as_tuple(std::get<_Is>(std::move(__t))...);200  }201 202  template <class... _Args, size_t... _Is>203  _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>204  __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, index_sequence<_Is...>) {205    using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;206    return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...);207  }208 209  template <class... _Args, size_t... _Is>210  _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&>211  __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, index_sequence<_Is...>) {212    using _Tup = tuple<_Args&&..., polymorphic_allocator&>;213    return _Tup(std::get<_Is>(std::move(__t))..., *this);214  }215 216  _LIBCPP_HIDE_FROM_ABI size_t __max_size() const noexcept {217    return numeric_limits<size_t>::max() / sizeof(value_type);218  }219 220  memory_resource* __res_;221};222 223// [mem.poly.allocator.eq]224 225template <class _Tp, class _Up>226inline _LIBCPP_HIDE_FROM_ABI bool227operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {228  return *__lhs.resource() == *__rhs.resource();229}230 231#  if _LIBCPP_STD_VER <= 17232 233template <class _Tp, class _Up>234inline _LIBCPP_HIDE_FROM_ABI bool235operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {236  return !(__lhs == __rhs);237}238 239#  endif240 241} // namespace pmr242 243_LIBCPP_END_NAMESPACE_STD244 245#endif // _LIBCPP_STD_VER >= 17246 247_LIBCPP_POP_MACROS248 249#endif // _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H250