]>
Commit | Line | Data |
---|---|---|
fe9571a3 JW |
1 | // Allocator that wraps operator new -*- C++ -*- |
2 | ||
a945c346 | 3 | // Copyright (C) 2001-2024 Free Software Foundation, Inc. |
fe9571a3 JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
25 | /** @file bits/new_allocator.h | |
26 | * This is an internal header file, included by other library headers. | |
27 | * Do not attempt to use it directly. @headername{memory} | |
28 | */ | |
29 | ||
30 | #ifndef _STD_NEW_ALLOCATOR_H | |
31 | #define _STD_NEW_ALLOCATOR_H 1 | |
32 | ||
33 | #include <bits/c++config.h> | |
34 | #include <new> | |
35 | #include <bits/functexcept.h> | |
36 | #include <bits/move.h> | |
37 | #if __cplusplus >= 201103L | |
38 | #include <type_traits> | |
39 | #endif | |
40 | ||
41 | namespace std _GLIBCXX_VISIBILITY(default) | |
42 | { | |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
44 | ||
45 | /** | |
171f41f1 JW |
46 | * @brief An allocator that uses global `new`, as per C++03 [20.4.1]. |
47 | * @ingroup allocators | |
fe9571a3 | 48 | * |
171f41f1 JW |
49 | * This is precisely the allocator defined in the C++ Standard. |
50 | * - all allocation calls `operator new` | |
51 | * - all deallocation calls `operator delete` | |
fe9571a3 | 52 | * |
171f41f1 JW |
53 | * This is the default base-class implementation of `std::allocator`, |
54 | * and is also the base-class of the `__gnu_cxx::new_allocator` extension. | |
55 | * You should use either `std::allocator` or `__gnu_cxx::new_allocator` | |
56 | * instead of using this directly. | |
57 | * | |
58 | * @tparam _Tp Type of allocated object. | |
59 | * | |
60 | * @headerfile memory | |
fe9571a3 JW |
61 | */ |
62 | template<typename _Tp> | |
63 | class __new_allocator | |
64 | { | |
65 | public: | |
66 | typedef _Tp value_type; | |
67 | typedef std::size_t size_type; | |
68 | typedef std::ptrdiff_t difference_type; | |
69 | #if __cplusplus <= 201703L | |
70 | typedef _Tp* pointer; | |
71 | typedef const _Tp* const_pointer; | |
72 | typedef _Tp& reference; | |
73 | typedef const _Tp& const_reference; | |
74 | ||
75 | template<typename _Tp1> | |
76 | struct rebind | |
77 | { typedef __new_allocator<_Tp1> other; }; | |
78 | #endif | |
79 | ||
80 | #if __cplusplus >= 201103L | |
81 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
82 | // 2103. propagate_on_container_move_assignment | |
83 | typedef std::true_type propagate_on_container_move_assignment; | |
84 | #endif | |
85 | ||
9d549401 | 86 | __attribute__((__always_inline__)) |
fe9571a3 JW |
87 | _GLIBCXX20_CONSTEXPR |
88 | __new_allocator() _GLIBCXX_USE_NOEXCEPT { } | |
89 | ||
9d549401 | 90 | __attribute__((__always_inline__)) |
fe9571a3 JW |
91 | _GLIBCXX20_CONSTEXPR |
92 | __new_allocator(const __new_allocator&) _GLIBCXX_USE_NOEXCEPT { } | |
93 | ||
94 | template<typename _Tp1> | |
9d549401 | 95 | __attribute__((__always_inline__)) |
fe9571a3 JW |
96 | _GLIBCXX20_CONSTEXPR |
97 | __new_allocator(const __new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } | |
98 | ||
008e439f JW |
99 | #if __cplusplus >= 201103L |
100 | __new_allocator& operator=(const __new_allocator&) = default; | |
101 | #endif | |
102 | ||
fe9571a3 JW |
103 | #if __cplusplus <= 201703L |
104 | ~__new_allocator() _GLIBCXX_USE_NOEXCEPT { } | |
105 | ||
106 | pointer | |
107 | address(reference __x) const _GLIBCXX_NOEXCEPT | |
108 | { return std::__addressof(__x); } | |
109 | ||
110 | const_pointer | |
111 | address(const_reference __x) const _GLIBCXX_NOEXCEPT | |
112 | { return std::__addressof(__x); } | |
113 | #endif | |
114 | ||
115 | #if __has_builtin(__builtin_operator_new) >= 201802L | |
116 | # define _GLIBCXX_OPERATOR_NEW __builtin_operator_new | |
117 | # define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete | |
118 | #else | |
119 | # define _GLIBCXX_OPERATOR_NEW ::operator new | |
120 | # define _GLIBCXX_OPERATOR_DELETE ::operator delete | |
121 | #endif | |
122 | ||
123 | // NB: __n is permitted to be 0. The C++ standard says nothing | |
124 | // about what the return value is when __n == 0. | |
125 | _GLIBCXX_NODISCARD _Tp* | |
126 | allocate(size_type __n, const void* = static_cast<const void*>(0)) | |
127 | { | |
128 | #if __cplusplus >= 201103L | |
29da0170 JW |
129 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
130 | // 3308. std::allocator<void>().allocate(n) | |
131 | static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types"); | |
fe9571a3 JW |
132 | #endif |
133 | ||
134 | if (__builtin_expect(__n > this->_M_max_size(), false)) | |
135 | { | |
136 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
137 | // 3190. allocator::allocate sometimes returns too little storage | |
138 | if (__n > (std::size_t(-1) / sizeof(_Tp))) | |
139 | std::__throw_bad_array_new_length(); | |
140 | std::__throw_bad_alloc(); | |
141 | } | |
142 | ||
03d3aeb0 | 143 | #if __cpp_aligned_new && __cplusplus >= 201103L |
fe9571a3 JW |
144 | if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) |
145 | { | |
146 | std::align_val_t __al = std::align_val_t(alignof(_Tp)); | |
147 | return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp), | |
148 | __al)); | |
149 | } | |
150 | #endif | |
151 | return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp))); | |
152 | } | |
153 | ||
154 | // __p is not permitted to be a null pointer. | |
155 | void | |
156 | deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__))) | |
157 | { | |
158 | #if __cpp_sized_deallocation | |
159 | # define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp) | |
160 | #else | |
161 | # define _GLIBCXX_SIZED_DEALLOC(p, n) (p) | |
162 | #endif | |
163 | ||
03d3aeb0 | 164 | #if __cpp_aligned_new && __cplusplus >= 201103L |
fe9571a3 JW |
165 | if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) |
166 | { | |
167 | _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n), | |
168 | std::align_val_t(alignof(_Tp))); | |
169 | return; | |
170 | } | |
171 | #endif | |
172 | _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n)); | |
173 | } | |
174 | ||
175 | #undef _GLIBCXX_SIZED_DEALLOC | |
176 | #undef _GLIBCXX_OPERATOR_DELETE | |
177 | #undef _GLIBCXX_OPERATOR_NEW | |
178 | ||
179 | #if __cplusplus <= 201703L | |
9d549401 | 180 | __attribute__((__always_inline__)) |
fe9571a3 JW |
181 | size_type |
182 | max_size() const _GLIBCXX_USE_NOEXCEPT | |
183 | { return _M_max_size(); } | |
184 | ||
185 | #if __cplusplus >= 201103L | |
186 | template<typename _Up, typename... _Args> | |
9d549401 | 187 | __attribute__((__always_inline__)) |
fe9571a3 JW |
188 | void |
189 | construct(_Up* __p, _Args&&... __args) | |
8cf51d75 | 190 | noexcept(__is_nothrow_new_constructible<_Up, _Args...>) |
fe9571a3 JW |
191 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } |
192 | ||
193 | template<typename _Up> | |
9d549401 | 194 | __attribute__((__always_inline__)) |
fe9571a3 JW |
195 | void |
196 | destroy(_Up* __p) | |
197 | noexcept(std::is_nothrow_destructible<_Up>::value) | |
198 | { __p->~_Up(); } | |
199 | #else | |
200 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
201 | // 402. wrong new expression in [some_] allocator::construct | |
9d549401 | 202 | __attribute__((__always_inline__)) |
fe9571a3 JW |
203 | void |
204 | construct(pointer __p, const _Tp& __val) | |
205 | { ::new((void *)__p) _Tp(__val); } | |
206 | ||
9d549401 | 207 | __attribute__((__always_inline__)) |
fe9571a3 JW |
208 | void |
209 | destroy(pointer __p) { __p->~_Tp(); } | |
210 | #endif | |
211 | #endif // ! C++20 | |
212 | ||
213 | template<typename _Up> | |
9d549401 | 214 | friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR bool |
fe9571a3 JW |
215 | operator==(const __new_allocator&, const __new_allocator<_Up>&) |
216 | _GLIBCXX_NOTHROW | |
217 | { return true; } | |
218 | ||
219 | #if __cpp_impl_three_way_comparison < 201907L | |
220 | template<typename _Up> | |
9d549401 | 221 | friend __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR bool |
fe9571a3 JW |
222 | operator!=(const __new_allocator&, const __new_allocator<_Up>&) |
223 | _GLIBCXX_NOTHROW | |
224 | { return false; } | |
225 | #endif | |
226 | ||
227 | private: | |
9d549401 | 228 | __attribute__((__always_inline__)) |
fe9571a3 JW |
229 | _GLIBCXX_CONSTEXPR size_type |
230 | _M_max_size() const _GLIBCXX_USE_NOEXCEPT | |
231 | { | |
232 | #if __PTRDIFF_MAX__ < __SIZE_MAX__ | |
233 | return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); | |
234 | #else | |
235 | return std::size_t(-1) / sizeof(_Tp); | |
236 | #endif | |
237 | } | |
238 | }; | |
239 | ||
240 | _GLIBCXX_END_NAMESPACE_VERSION | |
241 | } // namespace | |
242 | ||
243 | #endif |