Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:57

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
0010 #define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
0011 
0012 #include <__assert>
0013 #include <__config>
0014 #include <__cstddef/byte.h>
0015 #include <__cstddef/max_align_t.h>
0016 #include <__fwd/pair.h>
0017 #include <__memory_resource/memory_resource.h>
0018 #include <__new/exceptions.h>
0019 #include <__new/placement_new_delete.h>
0020 #include <__utility/exception_guard.h>
0021 #include <limits>
0022 #include <tuple>
0023 
0024 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0025 #  pragma GCC system_header
0026 #endif
0027 
0028 _LIBCPP_PUSH_MACROS
0029 #include <__undef_macros>
0030 
0031 #if _LIBCPP_STD_VER >= 17
0032 
0033 _LIBCPP_BEGIN_NAMESPACE_STD
0034 
0035 namespace pmr {
0036 
0037 // [mem.poly.allocator.class]
0038 
0039 template <class _ValueType
0040 #  if _LIBCPP_STD_VER >= 20
0041           = byte
0042 #  endif
0043           >
0044 class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
0045 
0046 public:
0047   using value_type = _ValueType;
0048 
0049   // [mem.poly.allocator.ctor]
0050 
0051   _LIBCPP_HIDE_FROM_ABI polymorphic_allocator() noexcept : __res_(std::pmr::get_default_resource()) {}
0052 
0053   _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {}
0054 
0055   _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default;
0056 
0057   template <class _Tp>
0058   _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept
0059       : __res_(__other.resource()) {}
0060 
0061   polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;
0062 
0063   // [mem.poly.allocator.mem]
0064 
0065   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) {
0066     if (__n > __max_size()) {
0067       __throw_bad_array_new_length();
0068     }
0069     return static_cast<_ValueType*>(__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType)));
0070   }
0071 
0072   _LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) {
0073     _LIBCPP_ASSERT_VALID_DEALLOCATION(
0074         __n <= __max_size(),
0075         "deallocate() called for a size which exceeds max_size(), leading to a memory leak "
0076         "(the argument will overflow and result in too few objects being deleted)");
0077     __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
0078   }
0079 
0080 #  if _LIBCPP_STD_VER >= 20
0081 
0082   [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void*
0083   allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
0084     return __res_->allocate(__nbytes, __alignment);
0085   }
0086 
0087   _LIBCPP_HIDE_FROM_ABI void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
0088     __res_->deallocate(__ptr, __nbytes, __alignment);
0089   }
0090 
0091   template <class _Type>
0092   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* allocate_object(size_t __n = 1) {
0093     if (numeric_limits<size_t>::max() / sizeof(_Type) < __n)
0094       std::__throw_bad_array_new_length();
0095     return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type)));
0096   }
0097 
0098   template <class _Type>
0099   _LIBCPP_HIDE_FROM_ABI void deallocate_object(_Type* __ptr, size_t __n = 1) {
0100     deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type));
0101   }
0102 
0103   template <class _Type, class... _CtorArgs>
0104   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* new_object(_CtorArgs&&... __ctor_args) {
0105     _Type* __ptr = allocate_object<_Type>();
0106     auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });
0107     construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);
0108     __guard.__complete();
0109     return __ptr;
0110   }
0111 
0112   template <class _Type>
0113   _LIBCPP_HIDE_FROM_ABI void delete_object(_Type* __ptr) {
0114     destroy(__ptr);
0115     deallocate_object(__ptr);
0116   }
0117 
0118 #  endif // _LIBCPP_STD_VER >= 20
0119 
0120   template <class _Tp, class... _Ts>
0121   _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) {
0122     std::__user_alloc_construct_impl(
0123         typename __uses_alloc_ctor<_Tp, polymorphic_allocator&, _Ts...>::type(),
0124         __p,
0125         *this,
0126         std::forward<_Ts>(__args)...);
0127   }
0128 
0129   template <class _T1, class _T2, class... _Args1, class... _Args2>
0130   _LIBCPP_HIDE_FROM_ABI void
0131   construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) {
0132     ::new ((void*)__p) pair<_T1, _T2>(
0133         piecewise_construct,
0134         __transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(),
0135                           std::move(__x),
0136                           typename __make_tuple_indices<sizeof...(_Args1)>::type{}),
0137         __transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(),
0138                           std::move(__y),
0139                           typename __make_tuple_indices<sizeof...(_Args2)>::type{}));
0140   }
0141 
0142   template <class _T1, class _T2>
0143   _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) {
0144     construct(__p, piecewise_construct, tuple<>(), tuple<>());
0145   }
0146 
0147   template <class _T1, class _T2, class _Up, class _Vp>
0148   _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) {
0149     construct(__p,
0150               piecewise_construct,
0151               std::forward_as_tuple(std::forward<_Up>(__u)),
0152               std::forward_as_tuple(std::forward<_Vp>(__v)));
0153   }
0154 
0155   template <class _T1, class _T2, class _U1, class _U2>
0156   _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_U1, _U2>& __pr) {
0157     construct(__p, piecewise_construct, std::forward_as_tuple(__pr.first), std::forward_as_tuple(__pr.second));
0158   }
0159 
0160   template <class _T1, class _T2, class _U1, class _U2>
0161   _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_U1, _U2>&& __pr) {
0162     construct(__p,
0163               piecewise_construct,
0164               std::forward_as_tuple(std::forward<_U1>(__pr.first)),
0165               std::forward_as_tuple(std::forward<_U2>(__pr.second)));
0166   }
0167 
0168   template <class _Tp>
0169   _LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) {
0170     __p->~_Tp();
0171   }
0172 
0173   _LIBCPP_HIDE_FROM_ABI polymorphic_allocator select_on_container_copy_construction() const noexcept {
0174     return polymorphic_allocator();
0175   }
0176 
0177   _LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }
0178 
0179   _LIBCPP_HIDE_FROM_ABI friend bool
0180   operator==(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {
0181     return *__lhs.resource() == *__rhs.resource();
0182   }
0183 
0184 #  if _LIBCPP_STD_VER <= 17
0185   // This overload is not specified, it was added due to LWG3683.
0186   _LIBCPP_HIDE_FROM_ABI friend bool
0187   operator!=(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {
0188     return *__lhs.resource() != *__rhs.resource();
0189   }
0190 #  endif
0191 
0192 private:
0193   template <class... _Args, size_t... _Is>
0194   _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...>
0195   __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0196     return std::forward_as_tuple(std::get<_Is>(std::move(__t))...);
0197   }
0198 
0199   template <class... _Args, size_t... _Is>
0200   _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
0201   __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0202     using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
0203     return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...);
0204   }
0205 
0206   template <class... _Args, size_t... _Is>
0207   _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&>
0208   __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0209     using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
0210     return _Tup(std::get<_Is>(std::move(__t))..., *this);
0211   }
0212 
0213   _LIBCPP_HIDE_FROM_ABI size_t __max_size() const noexcept {
0214     return numeric_limits<size_t>::max() / sizeof(value_type);
0215   }
0216 
0217   memory_resource* __res_;
0218 };
0219 
0220 // [mem.poly.allocator.eq]
0221 
0222 template <class _Tp, class _Up>
0223 inline _LIBCPP_HIDE_FROM_ABI bool
0224 operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
0225   return *__lhs.resource() == *__rhs.resource();
0226 }
0227 
0228 #  if _LIBCPP_STD_VER <= 17
0229 
0230 template <class _Tp, class _Up>
0231 inline _LIBCPP_HIDE_FROM_ABI bool
0232 operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
0233   return !(__lhs == __rhs);
0234 }
0235 
0236 #  endif
0237 
0238 } // namespace pmr
0239 
0240 _LIBCPP_END_NAMESPACE_STD
0241 
0242 #endif // _LIBCPP_STD_VER >= 17
0243 
0244 _LIBCPP_POP_MACROS
0245 
0246 #endif // _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H