1  // Allocator that wraps "C" malloc -*- C++ -*-
       2  
       3  // Copyright (C) 2001-2023 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 ext/malloc_allocator.h
      26   *  This file is a GNU extension to the Standard C++ Library.
      27   */
      28  
      29  #ifndef _MALLOC_ALLOCATOR_H
      30  #define _MALLOC_ALLOCATOR_H 1
      31  
      32  #include <bits/requires_hosted.h> // malloc
      33  
      34  #include <cstdlib>
      35  #include <cstddef>
      36  #include <new>
      37  #include <bits/functexcept.h>
      38  #include <bits/move.h>
      39  #if __cplusplus >= 201103L
      40  #include <type_traits>
      41  #endif
      42  
      43  namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
      44  {
      45  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      46  
      47    /**
      48     *  @brief  An allocator that uses malloc.
      49     *  @ingroup allocators
      50     *
      51     *  This is precisely the allocator defined in the C++ Standard. 
      52     *    - all allocation calls malloc
      53     *    - all deallocation calls free
      54     */
      55    template<typename _Tp>
      56      class malloc_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 malloc_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        malloc_allocator() _GLIBCXX_USE_NOEXCEPT { }
      81  
      82        _GLIBCXX20_CONSTEXPR
      83        malloc_allocator(const malloc_allocator&) _GLIBCXX_USE_NOEXCEPT { }
      84  
      85        template<typename _Tp1>
      86  	_GLIBCXX20_CONSTEXPR
      87          malloc_allocator(const malloc_allocator<_Tp1>&)
      88  	_GLIBCXX_USE_NOEXCEPT { }
      89  
      90  #if __cplusplus <= 201703L
      91        ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { }
      92  
      93        pointer
      94        address(reference __x) const _GLIBCXX_NOEXCEPT
      95        { return std::__addressof(__x); }
      96  
      97        const_pointer
      98        address(const_reference __x) const _GLIBCXX_NOEXCEPT
      99        { return std::__addressof(__x); }
     100  #endif
     101  
     102        // NB: __n is permitted to be 0.  The C++ standard says nothing
     103        // about what the return value is when __n == 0.
     104        _GLIBCXX_NODISCARD _Tp*
     105        allocate(size_type __n, const void* = 0)
     106        {
     107  #if __cplusplus >= 201103L
     108  	// _GLIBCXX_RESOLVE_LIB_DEFECTS
     109  	// 3308. std::allocator<void>().allocate(n)
     110  	static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types");
     111  #endif
     112  
     113  	if (__builtin_expect(__n > this->_M_max_size(), false))
     114  	  {
     115  	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
     116  	    // 3190. allocator::allocate sometimes returns too little storage
     117  	    if (__n > (std::size_t(-1) / sizeof(_Tp)))
     118  	      std::__throw_bad_array_new_length();
     119  	    std::__throw_bad_alloc();
     120  	  }
     121  
     122  	_Tp* __ret = 0;
     123  #if __cpp_aligned_new
     124  #if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC
     125  	if (alignof(_Tp) > alignof(std::max_align_t))
     126  	  {
     127  	    __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp),
     128  						      __n * sizeof(_Tp)));
     129  	  }
     130  #else
     131  # define _GLIBCXX_CHECK_MALLOC_RESULT
     132  #endif
     133  #endif
     134  	if (!__ret)
     135  	  __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp)));
     136  	if (!__ret)
     137  	  std::__throw_bad_alloc();
     138  #ifdef _GLIBCXX_CHECK_MALLOC_RESULT
     139  #undef _GLIBCXX_CHECK_MALLOC_RESULT
     140  	  if (reinterpret_cast<std::size_t>(__ret) % alignof(_Tp))
     141  	    {
     142  	      // Memory returned by malloc is not suitably aligned for _Tp.
     143  	      deallocate(__ret, __n);
     144  	      std::__throw_bad_alloc();
     145  	    }
     146  #endif
     147  	return __ret;
     148        }
     149  
     150        // __p is not permitted to be a null pointer.
     151        void
     152        deallocate(_Tp* __p, size_type)
     153        { std::free(static_cast<void*>(__p)); }
     154  
     155  #if __cplusplus <= 201703L
     156        size_type
     157        max_size() const _GLIBCXX_USE_NOEXCEPT 
     158        { return _M_max_size(); }
     159  
     160  #if __cplusplus >= 201103L
     161        template<typename _Up, typename... _Args>
     162          void
     163          construct(_Up* __p, _Args&&... __args)
     164  	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
     165  	{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
     166  
     167        template<typename _Up>
     168          void 
     169          destroy(_Up* __p)
     170  	noexcept(std::is_nothrow_destructible<_Up>::value)
     171  	{ __p->~_Up(); }
     172  #else
     173        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     174        // 402. wrong new expression in [some_] allocator::construct
     175        void
     176        construct(pointer __p, const _Tp& __val)
     177        { ::new((void *)__p) value_type(__val); }
     178  
     179        void
     180        destroy(pointer __p) { __p->~_Tp(); }
     181  #endif
     182  #endif // ! C++20
     183  
     184        template<typename _Up>
     185  	friend _GLIBCXX20_CONSTEXPR bool
     186  	operator==(const malloc_allocator&, const malloc_allocator<_Up>&)
     187  	_GLIBCXX_NOTHROW
     188  	{ return true; }
     189  
     190  #if __cpp_impl_three_way_comparison < 201907L
     191        template<typename _Up>
     192  	friend _GLIBCXX20_CONSTEXPR bool
     193  	operator!=(const malloc_allocator&, const malloc_allocator<_Up>&)
     194  	_GLIBCXX_NOTHROW
     195  	{ return false; }
     196  #endif
     197  
     198      private:
     199        _GLIBCXX_CONSTEXPR size_type
     200        _M_max_size() const _GLIBCXX_USE_NOEXCEPT
     201        {
     202  #if __PTRDIFF_MAX__ < __SIZE_MAX__
     203  	return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
     204  #else
     205  	return std::size_t(-1) / sizeof(_Tp);
     206  #endif
     207        }
     208      };
     209  
     210  _GLIBCXX_END_NAMESPACE_VERSION
     211  } // namespace
     212  
     213  #endif