File: polymorphic_allocator.h

package info (click to toggle)
llvm-toolchain-16 1%3A16.0.6-15~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,634,792 kB
  • sloc: cpp: 6,179,261; ansic: 1,216,205; asm: 741,319; python: 196,614; objc: 75,325; f90: 49,640; lisp: 32,396; pascal: 12,286; sh: 9,394; perl: 7,442; ml: 5,494; awk: 3,523; makefile: 2,723; javascript: 1,206; xml: 886; fortran: 581; cs: 573
file content (224 lines) | stat: -rw-r--r-- 7,739 bytes parent folder | download | duplicates (2)
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