libstdc++
|
00001 // <memory> -*- C++ -*- 00002 00003 // Copyright (C) 2001-2019 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /* 00026 * Copyright (c) 1997-1999 00027 * Silicon Graphics Computer Systems, Inc. 00028 * 00029 * Permission to use, copy, modify, distribute and sell this software 00030 * and its documentation for any purpose is hereby granted without fee, 00031 * provided that the above copyright notice appear in all copies and 00032 * that both that copyright notice and this permission notice appear 00033 * in supporting documentation. Silicon Graphics makes no 00034 * representations about the suitability of this software for any 00035 * purpose. It is provided "as is" without express or implied warranty. 00036 * 00037 */ 00038 00039 /** @file include/memory 00040 * This is a Standard C++ Library header. 00041 */ 00042 00043 #ifndef _GLIBCXX_MEMORY 00044 #define _GLIBCXX_MEMORY 1 00045 00046 #pragma GCC system_header 00047 00048 /** 00049 * @defgroup memory Memory 00050 * @ingroup utilities 00051 * 00052 * Components for memory allocation, deallocation, and management. 00053 */ 00054 00055 /** 00056 * @defgroup pointer_abstractions Pointer Abstractions 00057 * @ingroup memory 00058 * 00059 * Smart pointers, etc. 00060 */ 00061 00062 #include <bits/stl_algobase.h> 00063 #include <bits/allocator.h> 00064 #include <bits/stl_construct.h> 00065 #include <bits/stl_uninitialized.h> 00066 #include <bits/stl_tempbuf.h> 00067 #include <bits/stl_raw_storage_iter.h> 00068 00069 #if __cplusplus >= 201103L 00070 # include <exception> // std::exception 00071 # include <typeinfo> // std::type_info in get_deleter 00072 # include <iosfwd> // std::basic_ostream 00073 # include <ext/atomicity.h> 00074 # include <ext/concurrence.h> 00075 # include <bits/functexcept.h> 00076 # include <bits/stl_function.h> // std::less 00077 # include <bits/uses_allocator.h> 00078 # include <type_traits> 00079 # include <debug/debug.h> 00080 # include <bits/unique_ptr.h> 00081 # include <bits/shared_ptr.h> 00082 # include <bits/shared_ptr_atomic.h> 00083 # if _GLIBCXX_USE_DEPRECATED 00084 # include <backward/auto_ptr.h> 00085 # endif 00086 #else 00087 # include <backward/auto_ptr.h> 00088 #endif 00089 00090 #if __cplusplus >= 201103L 00091 #include <cstdint> 00092 #if __cplusplus > 201703L 00093 # include <bit> // for ispow2 00094 # include <new> // for placement operator new 00095 # include <tuple> // for tuple, make_tuple, make_from_tuple 00096 #endif 00097 namespace std _GLIBCXX_VISIBILITY(default) 00098 { 00099 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00100 00101 /** 00102 * @brief Fit aligned storage in buffer. 00103 * 00104 * [ptr.align] 00105 * 00106 * This function tries to fit @a __size bytes of storage with alignment 00107 * @a __align into the buffer @a __ptr of size @a __space bytes. If such 00108 * a buffer fits then @a __ptr is changed to point to the first byte of the 00109 * aligned storage and @a __space is reduced by the bytes used for alignment. 00110 * 00111 * @param __align A fundamental or extended alignment value. 00112 * @param __size Size of the aligned storage required. 00113 * @param __ptr Pointer to a buffer of @a __space bytes. 00114 * @param __space Size of the buffer pointed to by @a __ptr. 00115 * @return the updated pointer if the aligned storage fits, otherwise nullptr. 00116 */ 00117 inline void* 00118 align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept 00119 { 00120 #ifdef _GLIBCXX_USE_C99_STDINT_TR1 00121 const auto __intptr = reinterpret_cast<uintptr_t>(__ptr); 00122 #else 00123 // Cannot use std::uintptr_t so assume that std::size_t can be used instead. 00124 static_assert(sizeof(size_t) >= sizeof(void*), 00125 "std::size_t must be a suitable substitute for std::uintptr_t"); 00126 const auto __intptr = reinterpret_cast<unsigned long long>(__ptr); 00127 #endif 00128 const auto __aligned = (__intptr - 1u + __align) & -__align; 00129 const auto __diff = __aligned - __intptr; 00130 if ((__size + __diff) > __space) 00131 return nullptr; 00132 else 00133 { 00134 __space -= __diff; 00135 return __ptr = reinterpret_cast<void*>(__aligned); 00136 } 00137 } 00138 00139 // 20.7.4 [util.dynamic.safety], pointer safety 00140 00141 enum class pointer_safety { relaxed, preferred, strict }; 00142 00143 inline void 00144 declare_reachable(void*) { } 00145 00146 template <typename _Tp> 00147 inline _Tp* 00148 undeclare_reachable(_Tp* __p) { return __p; } 00149 00150 inline void 00151 declare_no_pointers(char*, size_t) { } 00152 00153 inline void 00154 undeclare_no_pointers(char*, size_t) { } 00155 00156 inline pointer_safety 00157 get_pointer_safety() noexcept { return pointer_safety::relaxed; } 00158 00159 #if __cplusplus > 201703L 00160 /// Inform the compiler that a pointer is aligned. 00161 template<size_t _Align, class _Tp> 00162 [[nodiscard,__gnu__::__always_inline__]] 00163 constexpr _Tp* assume_aligned(_Tp* __ptr) 00164 { 00165 static_assert(std::ispow2(_Align)); 00166 _GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0); 00167 return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align)); 00168 } 00169 #endif // C++2a 00170 00171 #if __cplusplus > 201703L 00172 template<typename _Tp> 00173 struct __is_pair : false_type { }; 00174 template<typename _Tp, typename _Up> 00175 struct __is_pair<pair<_Tp, _Up>> : true_type { }; 00176 template<typename _Tp, typename _Up> 00177 struct __is_pair<const pair<_Tp, _Up>> : true_type { }; 00178 00179 template<typename _Tp, typename __ = _Require<__not_<__is_pair<_Tp>>>, 00180 typename _Alloc, typename... _Args> 00181 constexpr auto 00182 __uses_alloc_args(const _Alloc& __a, _Args&&... __args) noexcept 00183 { 00184 if constexpr (uses_allocator_v<remove_cv_t<_Tp>, _Alloc>) 00185 { 00186 if constexpr (is_constructible_v<_Tp, allocator_arg_t, 00187 const _Alloc&, _Args...>) 00188 { 00189 return tuple<allocator_arg_t, const _Alloc&, _Args&&...>( 00190 allocator_arg, __a, std::forward<_Args>(__args)...); 00191 } 00192 else 00193 { 00194 static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>, 00195 "construction with an allocator must be possible" 00196 " if uses_allocator is true"); 00197 00198 return tuple<_Args&&..., const _Alloc&>( 00199 std::forward<_Args>(__args)..., __a); 00200 } 00201 } 00202 else 00203 { 00204 static_assert(is_constructible_v<_Tp, _Args...>); 00205 00206 return tuple<_Args&&...>(std::forward<_Args>(__args)...); 00207 } 00208 } 00209 00210 #if __cpp_concepts 00211 template<typename _Tp> 00212 concept _Std_pair = __is_pair<_Tp>::value; 00213 #endif 00214 00215 // This is a temporary workaround until -fconcepts is implied by -std=gnu++2a 00216 #if __cpp_concepts 00217 # define _GLIBCXX_STD_PAIR_CONSTRAINT(T) _Std_pair T 00218 # define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) _Std_pair T 00219 #else 00220 # define _GLIBCXX_STD_PAIR_CONSTRAINT(T) \ 00221 typename T, typename __ = _Require<__is_pair<T>> 00222 # define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) typename T, typename 00223 #endif 00224 00225 template<typename _Tp, 00226 #if ! __cpp_concepts 00227 typename __ = _Require<__not_<__is_pair<_Tp>>>, 00228 #endif 00229 typename _Alloc, typename... _Args> 00230 constexpr auto 00231 uses_allocator_construction_args(const _Alloc& __a, 00232 _Args&&... __args) noexcept 00233 #if __cpp_concepts 00234 requires ! _Std_pair<_Tp> 00235 #endif 00236 { 00237 return std::__uses_alloc_args<_Tp>(__a, std::forward<_Args>(__args)...); 00238 } 00239 00240 template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, 00241 typename _Tuple1, typename _Tuple2> 00242 constexpr auto 00243 uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, 00244 _Tuple1&& __x, _Tuple2&& __y) noexcept; 00245 00246 template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc> 00247 constexpr auto 00248 uses_allocator_construction_args(const _Alloc&) noexcept; 00249 00250 template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, 00251 typename _Up, typename _Vp> 00252 constexpr auto 00253 uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept; 00254 00255 template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, 00256 typename _Up, typename _Vp> 00257 constexpr auto 00258 uses_allocator_construction_args(const _Alloc&, 00259 const pair<_Up, _Vp>&) noexcept; 00260 00261 template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, 00262 typename _Up, typename _Vp> 00263 constexpr auto 00264 uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept; 00265 00266 template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, 00267 typename _Tuple1, typename _Tuple2> 00268 constexpr auto 00269 uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, 00270 _Tuple1&& __x, _Tuple2&& __y) noexcept 00271 { 00272 using _Tp1 = typename _Tp::first_type; 00273 using _Tp2 = typename _Tp::second_type; 00274 00275 return std::make_tuple(piecewise_construct, 00276 std::apply([&__a](auto&&... __args1) { 00277 return std::uses_allocator_construction_args<_Tp1>( 00278 __a, std::forward<decltype(__args1)>(__args1)...); 00279 }, std::forward<_Tuple1>(__x)), 00280 std::apply([&__a](auto&&... __args2) { 00281 return std::uses_allocator_construction_args<_Tp2>( 00282 __a, std::forward<decltype(__args2)>(__args2)...); 00283 }, std::forward<_Tuple2>(__y))); 00284 } 00285 00286 template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc> 00287 constexpr auto 00288 uses_allocator_construction_args(const _Alloc& __a) noexcept 00289 { 00290 using _Tp1 = typename _Tp::first_type; 00291 using _Tp2 = typename _Tp::second_type; 00292 00293 return std::make_tuple(piecewise_construct, 00294 std::uses_allocator_construction_args<_Tp1>(__a), 00295 std::uses_allocator_construction_args<_Tp2>(__a)); 00296 } 00297 00298 template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, 00299 typename _Up, typename _Vp> 00300 constexpr auto 00301 uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v) 00302 noexcept 00303 { 00304 using _Tp1 = typename _Tp::first_type; 00305 using _Tp2 = typename _Tp::second_type; 00306 00307 return std::make_tuple(piecewise_construct, 00308 std::uses_allocator_construction_args<_Tp1>(__a, 00309 std::forward<_Up>(__u)), 00310 std::uses_allocator_construction_args<_Tp2>(__a, 00311 std::forward<_Vp>(__v))); 00312 } 00313 00314 template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, 00315 typename _Up, typename _Vp> 00316 constexpr auto 00317 uses_allocator_construction_args(const _Alloc& __a, 00318 const pair<_Up, _Vp>& __pr) noexcept 00319 { 00320 using _Tp1 = typename _Tp::first_type; 00321 using _Tp2 = typename _Tp::second_type; 00322 00323 return std::make_tuple(piecewise_construct, 00324 std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), 00325 std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); 00326 } 00327 00328 template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, 00329 typename _Up, typename _Vp> 00330 constexpr auto 00331 uses_allocator_construction_args(const _Alloc& __a, 00332 pair<_Up, _Vp>&& __pr) noexcept 00333 { 00334 using _Tp1 = typename _Tp::first_type; 00335 using _Tp2 = typename _Tp::second_type; 00336 00337 return std::make_tuple(piecewise_construct, 00338 std::uses_allocator_construction_args<_Tp1>(__a, 00339 std::move(__pr).first), 00340 std::uses_allocator_construction_args<_Tp2>(__a, 00341 std::move(__pr).second)); 00342 } 00343 00344 template<typename _Tp, typename _Alloc, typename... _Args> 00345 inline _Tp 00346 make_obj_using_allocator(const _Alloc& __a, _Args&&... __args) 00347 { 00348 return std::make_from_tuple<_Tp>(uses_allocator_construction_args<_Tp>( 00349 __a, std::forward<_Args>(__args)...)); 00350 } 00351 00352 template<typename _Tp, typename _Alloc, typename... _Args> 00353 inline _Tp* 00354 uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a, 00355 _Args&&... __args) 00356 { 00357 void* __vp = const_cast<void*>(static_cast<const volatile void*>(__p)); 00358 return ::new(__vp) _Tp(std::make_obj_using_allocator<_Tp>(__a, 00359 std::forward<_Args>(__args)...)); 00360 } 00361 00362 #endif // C++2a 00363 00364 _GLIBCXX_END_NAMESPACE_VERSION 00365 } // namespace 00366 #endif // C++11 00367 00368 #if __cplusplus > 201402L 00369 // Parallel STL algorithms 00370 # if __PSTL_EXECUTION_POLICIES_DEFINED 00371 // If <execution> has already been included, pull in implementations 00372 # include <pstl/glue_memory_impl.h> 00373 # else 00374 // Otherwise just pull in forward declarations 00375 # include <pstl/glue_memory_defs.h> 00376 # endif 00377 00378 // Feature test macro for parallel algorithms 00379 # define __cpp_lib_parallel_algorithm 201703L 00380 #endif // C++17 00381 00382 #endif /* _GLIBCXX_MEMORY */