libstdc++
memory
Go to the documentation of this file.
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 */