(root)/
gcc-13.2.0/
libstdc++-v3/
include/
ext/
throw_allocator.h
       1  // -*- C++ -*-
       2  
       3  // Copyright (C) 2005-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 terms
       7  // of the GNU General Public License as published by the Free Software
       8  // Foundation; either version 3, or (at your option) any later
       9  // version.
      10  
      11  // This library is distributed in the hope that it will be useful, but
      12  // WITHOUT ANY WARRANTY; without even the implied warranty of
      13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14  // 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  // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
      26  
      27  // Permission to use, copy, modify, sell, and distribute this software
      28  // is hereby granted without fee, provided that the above copyright
      29  // notice appears in all copies, and that both that copyright notice
      30  // and this permission notice appear in supporting documentation. None
      31  // of the above authors, nor IBM Haifa Research Laboratories, make any
      32  // representation about the suitability of this software for any
      33  // purpose. It is provided "as is" without express or implied
      34  // warranty.
      35  
      36  /** @file ext/throw_allocator.h
      37   *  This file is a GNU extension to the Standard C++ Library.
      38   *
      39   *  Contains two exception-generating types (throw_value, throw_allocator)
      40   *  intended to be used as value and allocator types while testing
      41   *  exception safety in templatized containers and algorithms. The
      42   *  allocator has additional log and debug features. The exception
      43   *  generated is of type forced_exception_error.
      44   */
      45  
      46  #ifndef _THROW_ALLOCATOR_H
      47  #define _THROW_ALLOCATOR_H 1
      48  
      49  #include <bits/requires_hosted.h> // GNU extensions are currently omitted
      50  
      51  #include <cmath>
      52  #include <ctime>
      53  #include <map>
      54  #include <string>
      55  #include <ostream>
      56  #include <stdexcept>
      57  #include <utility>
      58  #include <bits/functexcept.h>
      59  #include <bits/move.h>
      60  #if __cplusplus >= 201103L
      61  # include <functional>
      62  # include <random>
      63  #else
      64  # include <tr1/functional>
      65  # include <tr1/random>
      66  #endif
      67  #include <ext/alloc_traits.h>
      68  
      69  #if !__has_builtin(__builtin_sprintf)
      70  # include <cstdio>
      71  #endif
      72  
      73  namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
      74  {
      75  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      76  
      77    /**
      78     *  @brief Thrown by utilities for testing exception safety.
      79     *  @ingroup exceptions
      80     */
      81    struct forced_error : public std::exception
      82    { };
      83  
      84    // Substitute for forced_error object when -fno-exceptions.
      85    inline void
      86    __throw_forced_error()
      87    { _GLIBCXX_THROW_OR_ABORT(forced_error()); }
      88  
      89    /**
      90     *  @brief Base class for checking address and label information
      91     *  about allocations. Create a std::map between the allocated
      92     *  address (void*) and a datum for annotations, which are a pair of
      93     *  numbers corresponding to label and allocated size.
      94     */
      95    struct annotate_base
      96    {
      97    private:
      98      typedef std::pair<size_t, size_t>		data_type;
      99      typedef std::map<void*, data_type>		map_alloc_type;
     100      typedef map_alloc_type::value_type		entry_type;
     101      typedef map_alloc_type::const_iterator	const_iterator;
     102      typedef map_alloc_type::const_reference	const_reference;
     103  #if __cplusplus >= 201103L
     104      typedef std::map<void*, size_t>		map_construct_type;
     105  #endif
     106  
     107    public:
     108      annotate_base()
     109      {
     110        label();
     111        map_alloc();
     112      }
     113  
     114      static void
     115      set_label(size_t l)
     116      { label() = l; }
     117  
     118      static size_t
     119      get_label()
     120      { return label(); }
     121  
     122      void
     123      insert(void* p, size_t size)
     124      {
     125        entry_type entry = make_entry(p, size);
     126        if (!p)
     127  	{
     128  	  std::string error("annotate_base::insert null insert!\n");
     129  	  log_to_string(error, entry);
     130  	  std::__throw_logic_error(error.c_str());
     131  	}
     132  
     133        std::pair<map_alloc_type::iterator, bool> inserted
     134  	= map_alloc().insert(entry);
     135        if (!inserted.second)
     136  	{
     137  	  std::string error("annotate_base::insert double insert!\n");
     138  	  log_to_string(error, entry);
     139  	  log_to_string(error, *inserted.first);
     140  	  std::__throw_logic_error(error.c_str());
     141  	}
     142      }
     143  
     144      void
     145      erase(void* p, size_t size)
     146      { map_alloc().erase(check_allocated(p, size)); }
     147  
     148  #if __cplusplus >= 201103L
     149      void
     150      insert_construct(void* p)
     151      {
     152        if (!p)
     153  	{
     154  	  std::string error("annotate_base::insert_construct null!\n");
     155  	  std::__throw_logic_error(error.c_str());
     156  	}
     157  
     158        auto inserted = map_construct().insert(std::make_pair(p, get_label()));
     159        if (!inserted.second)
     160  	{
     161  	  std::string error("annotate_base::insert_construct double insert!\n");
     162  	  log_to_string(error, std::make_pair(p, get_label()));
     163  	  log_to_string(error, *inserted.first);
     164  	  std::__throw_logic_error(error.c_str());
     165  	}
     166      }
     167  
     168      void
     169      erase_construct(void* p)
     170      { map_construct().erase(check_constructed(p)); }
     171  #endif
     172  
     173      // See if a particular address and allocation size has been saved.
     174      inline map_alloc_type::iterator
     175      check_allocated(void* p, size_t size)
     176      {
     177        map_alloc_type::iterator found = map_alloc().find(p);
     178        if (found == map_alloc().end())
     179  	{
     180  	  std::string error("annotate_base::check_allocated by value "
     181  			    "null erase!\n");
     182  	  log_to_string(error, make_entry(p, size));
     183  	  std::__throw_logic_error(error.c_str());
     184  	}
     185  
     186        if (found->second.second != size)
     187  	{
     188  	  std::string error("annotate_base::check_allocated by value "
     189  			    "wrong-size erase!\n");
     190  	  log_to_string(error, make_entry(p, size));
     191  	  log_to_string(error, *found);
     192  	  std::__throw_logic_error(error.c_str());
     193  	}
     194  
     195        return found;
     196      }
     197  
     198      // See if a given label has been allocated.
     199      inline void
     200      check(size_t label)
     201      {
     202        std::string found;
     203        {
     204  	const_iterator beg = map_alloc().begin();
     205  	const_iterator end = map_alloc().end();
     206  	while (beg != end)
     207  	  {
     208  	    if (beg->second.first == label)
     209  	      log_to_string(found, *beg);
     210  	    ++beg;
     211  	  }
     212        }
     213  
     214  #if __cplusplus >= 201103L
     215        {
     216  	auto beg = map_construct().begin();
     217  	auto end = map_construct().end();
     218  	while (beg != end)
     219  	  {
     220  	    if (beg->second == label)
     221  	      log_to_string(found, *beg);
     222  	    ++beg;
     223  	  }
     224        }
     225  #endif
     226  
     227        if (!found.empty())
     228  	{
     229  	  std::string error("annotate_base::check by label\n");
     230  	  error += found;
     231  	  std::__throw_logic_error(error.c_str());
     232  	}
     233      }
     234  
     235      // See if there is anything left allocated or constructed.
     236      inline static void
     237      check()
     238      {
     239        std::string found;
     240        {
     241  	const_iterator beg = map_alloc().begin();
     242  	const_iterator end = map_alloc().end();
     243  	while (beg != end)
     244  	  {
     245  	    log_to_string(found, *beg);
     246  	    ++beg;
     247  	  }
     248        }
     249  
     250  #if __cplusplus >= 201103L
     251        {
     252  	auto beg = map_construct().begin();
     253  	auto end = map_construct().end();
     254  	while (beg != end)
     255  	  {
     256  	    log_to_string(found, *beg);
     257  	    ++beg;
     258  	  }
     259        }
     260  #endif
     261  
     262        if (!found.empty())
     263  	{
     264  	  std::string error("annotate_base::check \n");
     265  	  error += found;
     266  	  std::__throw_logic_error(error.c_str());
     267  	}
     268      }
     269  
     270  #if __cplusplus >= 201103L
     271      inline map_construct_type::iterator
     272      check_constructed(void* p)
     273      {
     274        auto found = map_construct().find(p);
     275        if (found == map_construct().end())
     276  	{
     277  	  std::string error("annotate_base::check_constructed not "
     278  			    "constructed!\n");
     279  	  log_to_string(error, std::make_pair(p, get_label()));
     280  	  std::__throw_logic_error(error.c_str());
     281  	}
     282  
     283        return found;
     284      }
     285  
     286      inline void
     287      check_constructed(size_t label)
     288      {
     289        auto beg = map_construct().begin();
     290        auto end = map_construct().end();
     291        std::string found;
     292        while (beg != end)
     293  	{
     294  	  if (beg->second == label)
     295  	    log_to_string(found, *beg);
     296  	  ++beg;
     297  	}
     298  
     299        if (!found.empty())
     300  	{
     301  	  std::string error("annotate_base::check_constructed by label\n");
     302  	  error += found;
     303  	  std::__throw_logic_error(error.c_str());
     304  	}
     305      }
     306  #endif
     307  
     308    private:
     309      friend std::ostream&
     310      operator<<(std::ostream&, const annotate_base&);
     311  
     312      entry_type
     313      make_entry(void* p, size_t size)
     314      { return std::make_pair(p, data_type(get_label(), size)); }
     315  
     316      static void
     317      log_to_string(std::string& s, const_reference ref)
     318      {
     319  #if ! __has_builtin(__builtin_sprintf)
     320        __typeof__(&std::sprintf) __builtin_sprintf = &std::sprintf;
     321  #endif
     322  
     323        char buf[40];
     324        const char tab('\t');
     325        s += "label: ";
     326        unsigned long l = static_cast<unsigned long>(ref.second.first);
     327        __builtin_sprintf(buf, "%lu", l);
     328        s += buf;
     329        s += tab;
     330        s += "size: ";
     331        l = static_cast<unsigned long>(ref.second.second);
     332        __builtin_sprintf(buf, "%lu", l);
     333        s += buf;
     334        s += tab;
     335        s += "address: ";
     336        __builtin_sprintf(buf, "%p", ref.first);
     337        s += buf;
     338        s += '\n';
     339      }
     340  
     341  #if __cplusplus >= 201103L
     342      static void
     343      log_to_string(std::string& s, const std::pair<const void*, size_t>& ref)
     344      {
     345  #if ! __has_builtin(__builtin_sprintf)
     346        auto __builtin_sprintf = &std::sprintf;
     347  #endif
     348  
     349        char buf[40];
     350        const char tab('\t');
     351        s += "label: ";
     352        unsigned long l = static_cast<unsigned long>(ref.second);
     353        __builtin_sprintf(buf, "%lu", l);
     354        s += buf;
     355        s += tab;
     356        s += "address: ";
     357        __builtin_sprintf(buf, "%p", ref.first);
     358        s += buf;
     359        s += '\n';
     360      }
     361  #endif
     362  
     363      static size_t&
     364      label()
     365      {
     366        static size_t _S_label(std::numeric_limits<size_t>::max());
     367        return _S_label;
     368      }
     369  
     370      static map_alloc_type&
     371      map_alloc()
     372      {
     373        static map_alloc_type _S_map;
     374        return _S_map;
     375      }
     376  
     377  #if __cplusplus >= 201103L
     378      static map_construct_type&
     379      map_construct()
     380      {
     381        static map_construct_type _S_map;
     382        return _S_map;
     383      }
     384  #endif
     385    };
     386  
     387    inline std::ostream&
     388    operator<<(std::ostream& os, const annotate_base& __b)
     389    {
     390      std::string error;
     391      typedef annotate_base base_type;
     392      {
     393        base_type::const_iterator beg = __b.map_alloc().begin();
     394        base_type::const_iterator end = __b.map_alloc().end();
     395        for (; beg != end; ++beg)
     396  	__b.log_to_string(error, *beg);
     397      }
     398  #if __cplusplus >= 201103L
     399      {
     400        auto beg = __b.map_construct().begin();
     401        auto end = __b.map_construct().end();
     402        for (; beg != end; ++beg)
     403  	__b.log_to_string(error, *beg);      
     404      }
     405  #endif
     406      return os << error;
     407    }
     408  
     409  
     410    /**
     411     *  @brief Base struct for condition policy.
     412     *
     413     * Requires a public member function with the signature
     414     * void throw_conditionally()
     415     */
     416    struct condition_base
     417    {
     418  #if __cplusplus >= 201103L
     419      condition_base() = default;
     420      condition_base(const condition_base&) = default;
     421      condition_base& operator=(const condition_base&) = default;
     422  #endif
     423      virtual ~condition_base() { };
     424    };
     425  
     426  
     427    /**
     428     *  @brief Base class for incremental control and throw.
     429     */
     430    struct limit_condition : public condition_base
     431    {
     432      // Scope-level adjustor objects: set limit for throw at the
     433      // beginning of a scope block, and restores to previous limit when
     434      // object is destroyed on exiting the block.
     435      struct adjustor_base
     436      {
     437      private:
     438        const size_t _M_orig;
     439  
     440      public:
     441        adjustor_base() : _M_orig(limit()) { }
     442  
     443        virtual
     444        ~adjustor_base() { set_limit(_M_orig); }
     445      };
     446  
     447      /// Never enter the condition.
     448      struct never_adjustor : public adjustor_base
     449      {
     450        never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); }
     451      };
     452  
     453      /// Always enter the condition.
     454      struct always_adjustor : public adjustor_base
     455      {
     456        always_adjustor() { set_limit(count()); }
     457      };
     458  
     459      /// Enter the nth condition.
     460      struct limit_adjustor : public adjustor_base
     461      {
     462        limit_adjustor(const size_t __l) { set_limit(__l); }
     463      };
     464  
     465      // Increment _S_count every time called.
     466      // If _S_count matches the limit count, throw.
     467      static void
     468      throw_conditionally()
     469      {
     470        if (count() == limit())
     471  	__throw_forced_error();
     472        ++count();
     473      }
     474  
     475      static size_t&
     476      count()
     477      {
     478        static size_t _S_count(0);
     479        return _S_count;
     480      }
     481  
     482      static size_t&
     483      limit()
     484      {
     485        static size_t _S_limit(std::numeric_limits<size_t>::max());
     486        return _S_limit;
     487      }
     488  
     489      // Zero the throw counter, set limit to argument.
     490      static void
     491      set_limit(const size_t __l)
     492      {
     493        limit() = __l;
     494        count() = 0;
     495      }
     496    };
     497  
     498  #ifdef _GLIBCXX_USE_C99_STDINT_TR1
     499    /**
     500     *  @brief Base class for random probability control and throw.
     501     */
     502    struct random_condition : public condition_base
     503    {
     504      // Scope-level adjustor objects: set probability for throw at the
     505      // beginning of a scope block, and restores to previous
     506      // probability when object is destroyed on exiting the block.
     507      struct adjustor_base
     508      {
     509      private:
     510        const double _M_orig;
     511  
     512      public:
     513        adjustor_base() : _M_orig(probability()) { }
     514  
     515        virtual ~adjustor_base()
     516        { set_probability(_M_orig); }
     517      };
     518  
     519      /// Group condition.
     520      struct group_adjustor : public adjustor_base
     521      {
     522        group_adjustor(size_t size)
     523        { set_probability(1 - std::pow(double(1 - probability()),
     524  				     double(0.5 / (size + 1))));
     525        }
     526      };
     527  
     528      /// Never enter the condition.
     529      struct never_adjustor : public adjustor_base
     530      {
     531        never_adjustor() { set_probability(0); }
     532      };
     533  
     534      /// Always enter the condition.
     535      struct always_adjustor : public adjustor_base
     536      {
     537        always_adjustor() { set_probability(1); }
     538      };
     539  
     540      random_condition()
     541      {
     542        probability();
     543        engine();
     544      }
     545  
     546      static void
     547      set_probability(double __p)
     548      { probability() = __p; }
     549  
     550      static void
     551      throw_conditionally()
     552      {
     553        if (generate() < probability())
     554  	__throw_forced_error();
     555      }
     556  
     557      void
     558      seed(unsigned long __s)
     559      { engine().seed(__s); }
     560  
     561    private:
     562  #if __cplusplus >= 201103L
     563      typedef std::uniform_real_distribution<double> 	distribution_type;
     564      typedef std::mt19937 				engine_type;
     565  #else
     566      typedef std::tr1::uniform_real<double> 		distribution_type;
     567      typedef std::tr1::mt19937 				engine_type;
     568  #endif
     569  
     570      static double
     571      generate()
     572      {
     573  #if __cplusplus >= 201103L
     574        const distribution_type distribution(0, 1);
     575        static auto generator = std::bind(distribution, engine());
     576  #else
     577        // Use variate_generator to get normalized results.
     578        typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t;
     579        distribution_type distribution(0, 1);
     580        static gen_t generator(engine(), distribution);
     581  #endif
     582  
     583  #if ! __has_builtin(__builtin_sprintf)
     584        __typeof__(&std::sprintf) __builtin_sprintf = &std::sprintf;
     585  #endif
     586  
     587        double random = generator();
     588        if (random < distribution.min() || random > distribution.max())
     589  	{
     590  	  std::string __s("random_condition::generate");
     591  	  __s += "\n";
     592  	  __s += "random number generated is: ";
     593  	  char buf[40];
     594  	  __builtin_sprintf(buf, "%f", random);
     595  	  __s += buf;
     596  	  std::__throw_out_of_range(__s.c_str());
     597  	}
     598  
     599        return random;
     600      }
     601  
     602      static double&
     603      probability()
     604      {
     605        static double _S_p;
     606        return _S_p;
     607      }
     608  
     609      static engine_type&
     610      engine()
     611      {
     612        static engine_type _S_e;
     613        return _S_e;
     614      }
     615    };
     616  #endif // _GLIBCXX_USE_C99_STDINT_TR1
     617  
     618    /**
     619     *  @brief Class with exception generation control. Intended to be
     620     *  used as a value_type in templatized code.
     621     *
     622     *  Note: Destructor not allowed to throw.
     623     */
     624    template<typename _Cond>
     625      struct throw_value_base : public _Cond
     626      {
     627        typedef _Cond  				condition_type;
     628  
     629        using condition_type::throw_conditionally;
     630  
     631        std::size_t			       	_M_i;
     632  
     633  #ifndef _GLIBCXX_IS_AGGREGATE
     634        throw_value_base() : _M_i(0)
     635        { throw_conditionally(); }
     636  
     637        throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i)
     638        { throw_conditionally(); }
     639  
     640  #if __cplusplus >= 201103L
     641        // Shall not throw.
     642        throw_value_base(throw_value_base&&) = default;
     643  #endif
     644  
     645        explicit throw_value_base(const std::size_t __i) : _M_i(__i)
     646        { throw_conditionally(); }
     647  #endif
     648  
     649        throw_value_base&
     650        operator=(const throw_value_base& __v)
     651        {
     652  	throw_conditionally();
     653  	_M_i = __v._M_i;
     654  	return *this;
     655        }
     656  
     657  #if __cplusplus >= 201103L
     658        // Shall not throw.
     659        throw_value_base&
     660        operator=(throw_value_base&&) = default;
     661  #endif
     662  
     663        throw_value_base&
     664        operator++()
     665        {
     666  	throw_conditionally();
     667  	++_M_i;
     668  	return *this;
     669        }
     670      };
     671  
     672    template<typename _Cond>
     673      inline void
     674      swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b)
     675      {
     676        typedef throw_value_base<_Cond> throw_value;
     677        throw_value::throw_conditionally();
     678        throw_value orig(__a);
     679        __a = __b;
     680        __b = orig;
     681      }
     682  
     683    // General instantiable types requirements.
     684    template<typename _Cond>
     685      inline bool
     686      operator==(const throw_value_base<_Cond>& __a,
     687  	       const throw_value_base<_Cond>& __b)
     688      {
     689        typedef throw_value_base<_Cond> throw_value;
     690        throw_value::throw_conditionally();
     691        bool __ret = __a._M_i == __b._M_i;
     692        return __ret;
     693      }
     694  
     695    template<typename _Cond>
     696      inline bool
     697      operator<(const throw_value_base<_Cond>& __a,
     698  	      const throw_value_base<_Cond>& __b)
     699      {
     700        typedef throw_value_base<_Cond> throw_value;
     701        throw_value::throw_conditionally();
     702        bool __ret = __a._M_i < __b._M_i;
     703        return __ret;
     704      }
     705  
     706    // Numeric algorithms instantiable types requirements.
     707    template<typename _Cond>
     708      inline throw_value_base<_Cond>
     709      operator+(const throw_value_base<_Cond>& __a,
     710  	      const throw_value_base<_Cond>& __b)
     711      {
     712        typedef throw_value_base<_Cond> throw_value;
     713        throw_value::throw_conditionally();
     714        throw_value __ret(__a._M_i + __b._M_i);
     715        return __ret;
     716      }
     717  
     718    template<typename _Cond>
     719      inline throw_value_base<_Cond>
     720      operator-(const throw_value_base<_Cond>& __a,
     721  	      const throw_value_base<_Cond>& __b)
     722      {
     723        typedef throw_value_base<_Cond> throw_value;
     724        throw_value::throw_conditionally();
     725        throw_value __ret(__a._M_i - __b._M_i);
     726        return __ret;
     727      }
     728  
     729    template<typename _Cond>
     730      inline throw_value_base<_Cond>
     731      operator*(const throw_value_base<_Cond>& __a,
     732  	      const throw_value_base<_Cond>& __b)
     733      {
     734        typedef throw_value_base<_Cond> throw_value;
     735        throw_value::throw_conditionally();
     736        throw_value __ret(__a._M_i * __b._M_i);
     737        return __ret;
     738      }
     739  
     740  
     741    /// Type throwing via limit condition.
     742    struct throw_value_limit : public throw_value_base<limit_condition>
     743    {
     744      typedef throw_value_base<limit_condition> base_type;
     745  
     746  #ifndef _GLIBCXX_IS_AGGREGATE
     747      throw_value_limit() { }
     748  
     749      throw_value_limit(const throw_value_limit& __other)
     750      : base_type(__other._M_i) { }
     751  
     752  #if __cplusplus >= 201103L
     753      throw_value_limit(throw_value_limit&&) = default;
     754  #endif
     755  
     756      explicit throw_value_limit(const std::size_t __i) : base_type(__i) { }
     757  #endif
     758  
     759      throw_value_limit&
     760      operator=(const throw_value_limit& __other)
     761      {
     762        base_type::operator=(__other);
     763        return *this;
     764      }
     765  
     766  #if __cplusplus >= 201103L
     767      throw_value_limit&
     768      operator=(throw_value_limit&&) = default;
     769  #endif
     770    };
     771  
     772  #ifdef _GLIBCXX_USE_C99_STDINT_TR1
     773    /// Type throwing via random condition.
     774    struct throw_value_random : public throw_value_base<random_condition>
     775    {
     776      typedef throw_value_base<random_condition> base_type;
     777  
     778  #ifndef _GLIBCXX_IS_AGGREGATE
     779      throw_value_random() { }
     780  
     781      throw_value_random(const throw_value_random& __other)
     782      : base_type(__other._M_i) { }
     783  
     784  #if __cplusplus >= 201103L
     785      throw_value_random(throw_value_random&&) = default;
     786  #endif
     787  
     788      explicit throw_value_random(const std::size_t __i) : base_type(__i) { }
     789  #endif
     790  
     791      throw_value_random&
     792      operator=(const throw_value_random& __other)
     793      {
     794        base_type::operator=(__other);
     795        return *this;
     796      }
     797  
     798  #if __cplusplus >= 201103L
     799      throw_value_random&
     800      operator=(throw_value_random&&) = default;
     801  #endif
     802    };
     803  #endif // _GLIBCXX_USE_C99_STDINT_TR1
     804  
     805    /**
     806     *  @brief Allocator class with logging and exception generation control.
     807     * Intended to be used as an allocator_type in templatized code.
     808     *  @ingroup allocators
     809     *
     810     *  Note: Deallocate not allowed to throw.
     811     */
     812    template<typename _Tp, typename _Cond>
     813      class throw_allocator_base
     814      : public annotate_base, public _Cond
     815      {
     816      public:
     817        typedef std::size_t 			size_type;
     818        typedef std::ptrdiff_t 			difference_type;
     819        typedef _Tp 				value_type;
     820        typedef value_type* 			pointer;
     821        typedef const value_type* 		const_pointer;
     822        typedef value_type& 			reference;
     823        typedef const value_type& 		const_reference;
     824  
     825  #if __cplusplus >= 201103L
     826        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     827        // 2103. std::allocator propagate_on_container_move_assignment
     828        typedef std::true_type propagate_on_container_move_assignment;
     829  #endif
     830  
     831      private:
     832        typedef _Cond				condition_type;
     833  
     834        std::allocator<value_type> 		_M_allocator;
     835  
     836        typedef __gnu_cxx::__alloc_traits<std::allocator<value_type> > traits;
     837  
     838        using condition_type::throw_conditionally;
     839  
     840      public:
     841        size_type
     842        max_size() const _GLIBCXX_USE_NOEXCEPT
     843        { return traits::max_size(_M_allocator); }
     844  
     845        pointer
     846        address(reference __x) const _GLIBCXX_NOEXCEPT
     847        { return std::__addressof(__x); }
     848  
     849        const_pointer
     850        address(const_reference __x) const _GLIBCXX_NOEXCEPT
     851        { return std::__addressof(__x); }
     852  
     853        _GLIBCXX_NODISCARD pointer
     854        allocate(size_type __n, const void* __hint = 0)
     855        {
     856  	if (__n > this->max_size())
     857  	  std::__throw_bad_alloc();
     858  
     859  	throw_conditionally();
     860  	pointer const a = traits::allocate(_M_allocator, __n, __hint);
     861  	insert(a, sizeof(value_type) * __n);
     862  	return a;
     863        }
     864  
     865  #if __cplusplus >= 201103L
     866        template<typename _Up, typename... _Args>
     867          void
     868          construct(_Up* __p, _Args&&... __args)
     869  	{
     870  	  traits::construct(_M_allocator, __p, std::forward<_Args>(__args)...);
     871  	  insert_construct(__p);
     872  	}
     873  
     874        template<typename _Up>
     875          void 
     876          destroy(_Up* __p)
     877          {
     878  	  erase_construct(__p);
     879  	  traits::destroy(_M_allocator, __p);
     880  	}
     881  #else
     882        void
     883        construct(pointer __p, const value_type& __val)
     884        { return _M_allocator.construct(__p, __val); }
     885  
     886        void
     887        destroy(pointer __p)
     888        { _M_allocator.destroy(__p); }
     889  #endif
     890  
     891        void
     892        deallocate(pointer __p, size_type __n)
     893        {
     894  	erase(__p, sizeof(value_type) * __n);
     895  	_M_allocator.deallocate(__p, __n);
     896        }
     897  
     898        void
     899        check_allocated(pointer __p, size_type __n)
     900        {
     901  	size_type __t = sizeof(value_type) * __n;
     902  	annotate_base::check_allocated(__p, __t);
     903        }
     904  
     905        void
     906        check(size_type __n)
     907        { annotate_base::check(__n); }
     908    };
     909  
     910    template<typename _Tp, typename _Cond>
     911      inline bool
     912      operator==(const throw_allocator_base<_Tp, _Cond>&,
     913  	       const throw_allocator_base<_Tp, _Cond>&)
     914      { return true; }
     915  
     916  #if __cpp_impl_three_way_comparison < 201907L
     917    template<typename _Tp, typename _Cond>
     918      inline bool
     919      operator!=(const throw_allocator_base<_Tp, _Cond>&,
     920  	       const throw_allocator_base<_Tp, _Cond>&)
     921      { return false; }
     922  #endif
     923  
     924    /// Allocator throwing via limit condition.
     925    template<typename _Tp>
     926      struct throw_allocator_limit
     927      : public throw_allocator_base<_Tp, limit_condition>
     928      {
     929        template<typename _Tp1>
     930  	struct rebind
     931  	{ typedef throw_allocator_limit<_Tp1> other; };
     932  
     933        throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
     934  
     935        throw_allocator_limit(const throw_allocator_limit&)
     936        _GLIBCXX_USE_NOEXCEPT { }
     937  
     938        template<typename _Tp1>
     939  	throw_allocator_limit(const throw_allocator_limit<_Tp1>&)
     940  	_GLIBCXX_USE_NOEXCEPT { }
     941  
     942        ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
     943  
     944  #if __cplusplus >= 201103L
     945        throw_allocator_limit&
     946        operator=(const throw_allocator_limit&) = default;
     947  #endif
     948      };
     949  
     950  #ifdef _GLIBCXX_USE_C99_STDINT_TR1
     951    /// Allocator throwing via random condition.
     952    template<typename _Tp>
     953      struct throw_allocator_random
     954      : public throw_allocator_base<_Tp, random_condition>
     955      {
     956        template<typename _Tp1>
     957  	struct rebind
     958  	{ typedef throw_allocator_random<_Tp1> other; };
     959  
     960        throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
     961  
     962        throw_allocator_random(const throw_allocator_random&)
     963        _GLIBCXX_USE_NOEXCEPT { }
     964  
     965        template<typename _Tp1>
     966  	throw_allocator_random(const throw_allocator_random<_Tp1>&)
     967  	_GLIBCXX_USE_NOEXCEPT { }
     968  
     969        ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
     970  
     971  #if __cplusplus >= 201103L
     972        throw_allocator_random&
     973        operator=(const throw_allocator_random&) = default;
     974  #endif
     975      };
     976  #endif // _GLIBCXX_USE_C99_STDINT_TR1
     977  
     978  _GLIBCXX_END_NAMESPACE_VERSION
     979  } // namespace
     980  
     981  #if __cplusplus >= 201103L
     982  
     983  # include <bits/functional_hash.h>
     984  
     985  namespace std _GLIBCXX_VISIBILITY(default)
     986  {
     987  #pragma GCC diagnostic push
     988  #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     989  
     990    /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit.
     991    template<>
     992      struct hash<__gnu_cxx::throw_value_limit>
     993      : public std::unary_function<__gnu_cxx::throw_value_limit, size_t>
     994      {
     995        size_t
     996        operator()(const __gnu_cxx::throw_value_limit& __val) const
     997        {
     998  	__gnu_cxx::throw_value_limit::throw_conditionally();
     999  	std::hash<std::size_t> __h;
    1000  	size_t __result = __h(__val._M_i);
    1001  	return __result;
    1002        }
    1003      };
    1004  
    1005  #ifdef _GLIBCXX_USE_C99_STDINT_TR1
    1006    /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random.
    1007    template<>
    1008      struct hash<__gnu_cxx::throw_value_random>
    1009      : public std::unary_function<__gnu_cxx::throw_value_random, size_t>
    1010      {
    1011        size_t
    1012        operator()(const __gnu_cxx::throw_value_random& __val) const
    1013        {
    1014  	__gnu_cxx::throw_value_random::throw_conditionally();
    1015  	std::hash<std::size_t> __h;
    1016  	size_t __result = __h(__val._M_i);
    1017  	return __result;
    1018        }
    1019      };
    1020  #endif
    1021  
    1022  #pragma GCC diagnostic pop
    1023  } // end namespace std
    1024  #endif
    1025  
    1026  #endif