(root)/
gcc-13.2.0/
libstdc++-v3/
include/
ext/
debug_allocator.h
       1  // Allocators -*- 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  /*
      26   * Copyright (c) 1996-1997
      27   * Silicon Graphics Computer Systems, Inc.
      28   *
      29   * Permission to use, copy, modify, distribute and sell this software
      30   * and its documentation for any purpose is hereby granted without fee,
      31   * provided that the above copyright notice appear in all copies and
      32   * that both that copyright notice and this permission notice appear
      33   * in supporting documentation.  Silicon Graphics makes no
      34   * representations about the suitability of this software for any
      35   * purpose.  It is provided "as is" without express or implied warranty.
      36   */
      37  
      38  /** @file ext/debug_allocator.h
      39   *  This file is a GNU extension to the Standard C++ Library.
      40   */
      41  
      42  #ifndef _DEBUG_ALLOCATOR_H
      43  #define _DEBUG_ALLOCATOR_H 1
      44  
      45  #include <bits/requires_hosted.h> // GNU extensions are currently omitted
      46  
      47  #include <stdexcept>
      48  #include <bits/functexcept.h>
      49  #include <ext/alloc_traits.h>
      50  
      51  namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
      52  {
      53  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      54  
      55    /**
      56     *  @brief  A meta-allocator with debugging bits.
      57     *  @ingroup allocators
      58     *
      59     *  This is precisely the allocator defined in the C++03 Standard.
      60     */
      61    template<typename _Alloc>
      62      class debug_allocator
      63      {
      64        template<typename> friend class debug_allocator;
      65  
      66        typedef __alloc_traits<_Alloc> _Traits;
      67  
      68      public:
      69        typedef typename _Traits::size_type       	size_type;
      70        typedef typename _Traits::difference_type	difference_type;
      71        typedef typename _Traits::pointer       	pointer;
      72        typedef typename _Traits::const_pointer    const_pointer;
      73        typedef typename _Traits::reference       	reference;
      74        typedef typename _Traits::const_reference  const_reference;
      75        typedef typename _Traits::value_type       value_type;
      76  
      77        template<typename _Up>
      78  	class rebind
      79  	{
      80  	  typedef typename _Traits::template rebind<_Up>::other __other;
      81  
      82  	public:
      83  	  typedef debug_allocator<__other> other;
      84  	};
      85  
      86      private:
      87        // _M_extra is the number of objects that correspond to the
      88        // extra space where debug information is stored.
      89        size_type 		_M_extra;
      90        
      91        _Alloc			_M_allocator;
      92  
      93        template<typename _Alloc2,
      94  	       typename = typename __alloc_traits<_Alloc2>::template
      95  			   rebind<value_type>::other>
      96  	struct __convertible
      97  	{ };
      98  
      99        template<typename _Alloc2>
     100  	struct __convertible<_Alloc2, _Alloc>
     101  	{
     102  	  typedef void* __type;
     103  	};
     104  
     105        size_type _S_extra()
     106        {
     107  	const std::size_t __obj_size = sizeof(value_type);
     108  	return (sizeof(size_type) + __obj_size - 1) / __obj_size; 
     109        }
     110  
     111      public:
     112        debug_allocator() : _M_extra(_S_extra()) { }
     113  
     114        template<typename _Alloc2>
     115  	debug_allocator(const debug_allocator<_Alloc2>& __a2,
     116  			typename __convertible<_Alloc2>::__type = 0)
     117  	: _M_extra(_S_extra()), _M_allocator(__a2._M_allocator)  { }
     118  
     119        debug_allocator(const _Alloc& __a)
     120        : _M_extra(_S_extra()), _M_allocator(__a)  { }
     121  
     122        _GLIBCXX_NODISCARD pointer
     123        allocate(size_type __n)
     124        {
     125          pointer __res = _M_allocator.allocate(__n + _M_extra);      
     126  	size_type* __ps = reinterpret_cast<size_type*>(__res);
     127  	*__ps = __n;
     128          return __res + _M_extra;
     129        }
     130  
     131        _GLIBCXX_NODISCARD pointer
     132        allocate(size_type __n, const void* __hint)
     133        {
     134          pointer __res = _M_allocator.allocate(__n + _M_extra, __hint);
     135  	size_type* __ps = reinterpret_cast<size_type*>(__res);
     136  	*__ps = __n;
     137          return __res + _M_extra;
     138        }
     139  
     140        void
     141        deallocate(pointer __p, size_type __n)
     142        {
     143  	using std::__throw_runtime_error;
     144  	if (__p)
     145  	  {
     146  	    pointer __real_p = __p - _M_extra;
     147  	    if (*reinterpret_cast<size_type*>(__real_p) != __n)
     148  	      __throw_runtime_error("debug_allocator::deallocate wrong size");
     149  	    _M_allocator.deallocate(__real_p, __n + _M_extra);
     150  	  }
     151  	else
     152  	  __throw_runtime_error("debug_allocator::deallocate null pointer");
     153        }
     154  
     155        void
     156        construct(pointer __p, const value_type& __val)
     157        { _Traits::construct(_M_allocator, __p, __val); }
     158  
     159  #if __cplusplus >= 201103L
     160        template<typename _Tp, typename... _Args>
     161  	void
     162  	construct(_Tp* __p, _Args&&... __args)
     163  	{
     164  	  _Traits::construct(_M_allocator, __p,
     165  			     std::forward<_Args>(__args)...);
     166  	}
     167  #endif
     168  
     169        template<typename _Tp>
     170  	void
     171  	destroy(_Tp* __p)
     172  	{ _Traits::destroy(_M_allocator, __p); }
     173  
     174        size_type
     175        max_size() const throw()
     176        { return _Traits::max_size(_M_allocator) - _M_extra; }
     177  
     178        template<typename _Alloc2>
     179  	friend bool
     180  	operator==(const debug_allocator& __lhs,
     181  		   const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
     182  	{ return __lhs._M_allocator == debug_allocator(__rhs)._M_allocator; }
     183  
     184  #if __cpp_impl_three_way_comparison < 201907L
     185        template<typename _Alloc2>
     186  	friend bool
     187  	operator!=(const debug_allocator& __lhs,
     188  		   const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
     189  	{ return !(__lhs == __rhs); }
     190  #endif
     191      };
     192  
     193  _GLIBCXX_END_NAMESPACE_VERSION
     194  } // namespace
     195  
     196  #endif