libstdc++
|
00001 // Allocator that wraps "C" malloc -*- 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 /** @file ext/malloc_allocator.h 00026 * This file is a GNU extension to the Standard C++ Library. 00027 */ 00028 00029 #ifndef _MALLOC_ALLOCATOR_H 00030 #define _MALLOC_ALLOCATOR_H 1 00031 00032 #include <cstdlib> 00033 #include <cstddef> 00034 #include <new> 00035 #include <bits/functexcept.h> 00036 #include <bits/move.h> 00037 #if __cplusplus >= 201103L 00038 #include <type_traits> 00039 #endif 00040 00041 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 00042 { 00043 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00044 00045 using std::size_t; 00046 using std::ptrdiff_t; 00047 00048 /** 00049 * @brief An allocator that uses malloc. 00050 * @ingroup allocators 00051 * 00052 * This is precisely the allocator defined in the C++ Standard. 00053 * - all allocation calls malloc 00054 * - all deallocation calls free 00055 */ 00056 template<typename _Tp> 00057 class malloc_allocator 00058 { 00059 public: 00060 typedef size_t size_type; 00061 typedef ptrdiff_t difference_type; 00062 typedef _Tp* pointer; 00063 typedef const _Tp* const_pointer; 00064 typedef _Tp& reference; 00065 typedef const _Tp& const_reference; 00066 typedef _Tp value_type; 00067 00068 template<typename _Tp1> 00069 struct rebind 00070 { typedef malloc_allocator<_Tp1> other; }; 00071 00072 #if __cplusplus >= 201103L 00073 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00074 // 2103. propagate_on_container_move_assignment 00075 typedef std::true_type propagate_on_container_move_assignment; 00076 #endif 00077 00078 _GLIBCXX20_CONSTEXPR 00079 malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } 00080 00081 _GLIBCXX20_CONSTEXPR 00082 malloc_allocator(const malloc_allocator&) _GLIBCXX_USE_NOEXCEPT { } 00083 00084 template<typename _Tp1> 00085 _GLIBCXX20_CONSTEXPR 00086 malloc_allocator(const malloc_allocator<_Tp1>&) 00087 _GLIBCXX_USE_NOEXCEPT { } 00088 00089 ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } 00090 00091 pointer 00092 address(reference __x) const _GLIBCXX_NOEXCEPT 00093 { return std::__addressof(__x); } 00094 00095 const_pointer 00096 address(const_reference __x) const _GLIBCXX_NOEXCEPT 00097 { return std::__addressof(__x); } 00098 00099 // NB: __n is permitted to be 0. The C++ standard says nothing 00100 // about what the return value is when __n == 0. 00101 pointer 00102 allocate(size_type __n, const void* = 0) 00103 { 00104 if (__n > this->max_size()) 00105 std::__throw_bad_alloc(); 00106 00107 pointer __ret = 0; 00108 #if __cpp_aligned_new 00109 #if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC 00110 if (alignof(_Tp) > alignof(std::max_align_t)) 00111 { 00112 __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp), 00113 __n * sizeof(_Tp))); 00114 } 00115 #else 00116 # define _GLIBCXX_CHECK_MALLOC_RESULT 00117 #endif 00118 #endif 00119 if (!__ret) 00120 __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); 00121 if (!__ret) 00122 std::__throw_bad_alloc(); 00123 #ifdef _GLIBCXX_CHECK_MALLOC_RESULT 00124 #undef _GLIBCXX_CHECK_MALLOC_RESULT 00125 if (reinterpret_cast<std::size_t>(__ret) % alignof(_Tp)) 00126 { 00127 // Memory returned by malloc is not suitably aligned for _Tp. 00128 deallocate(__ret, __n); 00129 std::__throw_bad_alloc(); 00130 } 00131 #endif 00132 return __ret; 00133 } 00134 00135 // __p is not permitted to be a null pointer. 00136 void 00137 deallocate(pointer __p, size_type) 00138 { std::free(static_cast<void*>(__p)); } 00139 00140 size_type 00141 max_size() const _GLIBCXX_USE_NOEXCEPT 00142 { 00143 #if __PTRDIFF_MAX__ < __SIZE_MAX__ 00144 return size_t(__PTRDIFF_MAX__) / sizeof(_Tp); 00145 #else 00146 return size_t(-1) / sizeof(_Tp); 00147 #endif 00148 } 00149 00150 #if __cplusplus >= 201103L 00151 template<typename _Up, typename... _Args> 00152 void 00153 construct(_Up* __p, _Args&&... __args) 00154 noexcept(noexcept(::new((void *)__p) 00155 _Up(std::forward<_Args>(__args)...))) 00156 { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 00157 00158 template<typename _Up> 00159 void 00160 destroy(_Up* __p) 00161 noexcept(noexcept(__p->~_Up())) 00162 { __p->~_Up(); } 00163 #else 00164 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00165 // 402. wrong new expression in [some_] allocator::construct 00166 void 00167 construct(pointer __p, const _Tp& __val) 00168 { ::new((void *)__p) value_type(__val); } 00169 00170 void 00171 destroy(pointer __p) { __p->~_Tp(); } 00172 #endif 00173 00174 template<typename _Up> 00175 friend bool 00176 operator==(const malloc_allocator&, const malloc_allocator<_Up>&) 00177 _GLIBCXX_NOTHROW 00178 { return true; } 00179 00180 template<typename _Up> 00181 friend bool 00182 operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) 00183 _GLIBCXX_NOTHROW 00184 { return false; } 00185 }; 00186 00187 _GLIBCXX_END_NAMESPACE_VERSION 00188 } // namespace 00189 00190 #endif