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