1 | // Allocator that wraps operator new -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2022 Free Software Foundation, Inc. |
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 | /** |
46 | * @brief An allocator that uses global new, as per C++03 [20.4.1]. |
47 | * @ingroup allocators |
48 | * |
49 | * This is precisely the allocator defined in the C++ Standard. |
50 | * - all allocation calls operator new |
51 | * - all deallocation calls operator delete |
52 | * |
53 | * @tparam _Tp Type of allocated object. |
54 | */ |
55 | template<typename _Tp> |
56 | class __new_allocator |
57 | { |
58 | public: |
59 | typedef _Tp value_type; |
60 | typedef std::size_t size_type; |
61 | typedef std::ptrdiff_t difference_type; |
62 | #if __cplusplus <= 201703L |
63 | typedef _Tp* pointer; |
64 | typedef const _Tp* const_pointer; |
65 | typedef _Tp& reference; |
66 | typedef const _Tp& const_reference; |
67 | |
68 | template<typename _Tp1> |
69 | struct rebind |
70 | { typedef __new_allocator<_Tp1> other; }; |
71 | #endif |
72 | |
73 | #if __cplusplus >= 201103L |
74 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
75 | // 2103. propagate_on_container_move_assignment |
76 | typedef std::true_type propagate_on_container_move_assignment; |
77 | #endif |
78 | |
79 | _GLIBCXX20_CONSTEXPR |
80 | __new_allocator() _GLIBCXX_USE_NOEXCEPT { } |
81 | |
82 | _GLIBCXX20_CONSTEXPR |
83 | __new_allocator(const __new_allocator&) _GLIBCXX_USE_NOEXCEPT { } |
84 | |
85 | template<typename _Tp1> |
86 | _GLIBCXX20_CONSTEXPR |
87 | __new_allocator(const __new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } |
88 | |
89 | #if __cplusplus <= 201703L |
90 | ~__new_allocator() _GLIBCXX_USE_NOEXCEPT { } |
91 | |
92 | pointer |
93 | address(reference __x) const _GLIBCXX_NOEXCEPT |
94 | { return std::__addressof(__x); } |
95 | |
96 | const_pointer |
97 | address(const_reference __x) const _GLIBCXX_NOEXCEPT |
98 | { return std::__addressof(__x); } |
99 | #endif |
100 | |
101 | #if __has_builtin(__builtin_operator_new) >= 201802L |
102 | # define _GLIBCXX_OPERATOR_NEW __builtin_operator_new |
103 | # define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete |
104 | #else |
105 | # define _GLIBCXX_OPERATOR_NEW ::operator new |
106 | # define _GLIBCXX_OPERATOR_DELETE ::operator delete |
107 | #endif |
108 | |
109 | // NB: __n is permitted to be 0. The C++ standard says nothing |
110 | // about what the return value is when __n == 0. |
111 | _GLIBCXX_NODISCARD _Tp* |
112 | allocate(size_type __n, const void* = static_cast<const void*>(0)) |
113 | { |
114 | #if __cplusplus >= 201103L |
115 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
116 | // 3308. std::allocator<void>().allocate(n) |
117 | static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types" ); |
118 | #endif |
119 | |
120 | if (__builtin_expect(__n > this->_M_max_size(), false)) |
121 | { |
122 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
123 | // 3190. allocator::allocate sometimes returns too little storage |
124 | if (__n > (std::size_t(-1) / sizeof(_Tp))) |
125 | std::__throw_bad_array_new_length(); |
126 | std::__throw_bad_alloc(); |
127 | } |
128 | |
129 | #if __cpp_aligned_new |
130 | if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) |
131 | { |
132 | std::align_val_t __al = std::align_val_t(alignof(_Tp)); |
133 | return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp), |
134 | __al)); |
135 | } |
136 | #endif |
137 | return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp))); |
138 | } |
139 | |
140 | // __p is not permitted to be a null pointer. |
141 | void |
142 | deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__))) |
143 | { |
144 | #if __cpp_sized_deallocation |
145 | # define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp) |
146 | #else |
147 | # define _GLIBCXX_SIZED_DEALLOC(p, n) (p) |
148 | #endif |
149 | |
150 | #if __cpp_aligned_new |
151 | if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) |
152 | { |
153 | _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n), |
154 | std::align_val_t(alignof(_Tp))); |
155 | return; |
156 | } |
157 | #endif |
158 | _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n)); |
159 | } |
160 | |
161 | #undef _GLIBCXX_SIZED_DEALLOC |
162 | #undef _GLIBCXX_OPERATOR_DELETE |
163 | #undef _GLIBCXX_OPERATOR_NEW |
164 | |
165 | #if __cplusplus <= 201703L |
166 | size_type |
167 | max_size() const _GLIBCXX_USE_NOEXCEPT |
168 | { return _M_max_size(); } |
169 | |
170 | #if __cplusplus >= 201103L |
171 | template<typename _Up, typename... _Args> |
172 | void |
173 | construct(_Up* __p, _Args&&... __args) |
174 | noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) |
175 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } |
176 | |
177 | template<typename _Up> |
178 | void |
179 | destroy(_Up* __p) |
180 | noexcept(std::is_nothrow_destructible<_Up>::value) |
181 | { __p->~_Up(); } |
182 | #else |
183 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
184 | // 402. wrong new expression in [some_] allocator::construct |
185 | void |
186 | construct(pointer __p, const _Tp& __val) |
187 | { ::new((void *)__p) _Tp(__val); } |
188 | |
189 | void |
190 | destroy(pointer __p) { __p->~_Tp(); } |
191 | #endif |
192 | #endif // ! C++20 |
193 | |
194 | template<typename _Up> |
195 | friend _GLIBCXX20_CONSTEXPR bool |
196 | operator==(const __new_allocator&, const __new_allocator<_Up>&) |
197 | _GLIBCXX_NOTHROW |
198 | { return true; } |
199 | |
200 | #if __cpp_impl_three_way_comparison < 201907L |
201 | template<typename _Up> |
202 | friend _GLIBCXX20_CONSTEXPR bool |
203 | operator!=(const __new_allocator&, const __new_allocator<_Up>&) |
204 | _GLIBCXX_NOTHROW |
205 | { return false; } |
206 | #endif |
207 | |
208 | private: |
209 | _GLIBCXX_CONSTEXPR size_type |
210 | _M_max_size() const _GLIBCXX_USE_NOEXCEPT |
211 | { |
212 | #if __PTRDIFF_MAX__ < __SIZE_MAX__ |
213 | return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); |
214 | #else |
215 | return std::size_t(-1) / sizeof(_Tp); |
216 | #endif |
217 | } |
218 | }; |
219 | |
220 | _GLIBCXX_END_NAMESPACE_VERSION |
221 | } // namespace |
222 | |
223 | #endif |
224 | |