mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			981 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			981 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
	
| // -*- C++ -*-
 | |
| 
 | |
| // Copyright (C) 2005-2018 Free Software Foundation, Inc.
 | |
| //
 | |
| // This file is part of the GNU ISO C++ Library.  This library is free
 | |
| // software; you can redistribute it and/or modify it under the terms
 | |
| // of the GNU General Public License as published by the Free Software
 | |
| // Foundation; either version 3, or (at your option) any later
 | |
| // version.
 | |
| 
 | |
| // This library is distributed in the hope that it will be useful, but
 | |
| // WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| // General Public License for more details.
 | |
| 
 | |
| // Under Section 7 of GPL version 3, you are granted additional
 | |
| // permissions described in the GCC Runtime Library Exception, version
 | |
| // 3.1, as published by the Free Software Foundation.
 | |
| 
 | |
| // You should have received a copy of the GNU General Public License and
 | |
| // a copy of the GCC Runtime Library Exception along with this program;
 | |
| // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 | |
| // <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
 | |
| 
 | |
| // Permission to use, copy, modify, sell, and distribute this software
 | |
| // is hereby granted without fee, provided that the above copyright
 | |
| // notice appears in all copies, and that both that copyright notice
 | |
| // and this permission notice appear in supporting documentation. None
 | |
| // of the above authors, nor IBM Haifa Research Laboratories, make any
 | |
| // representation about the suitability of this software for any
 | |
| // purpose. It is provided "as is" without express or implied
 | |
| // warranty.
 | |
| 
 | |
| /** @file ext/throw_allocator.h
 | |
|  *  This file is a GNU extension to the Standard C++ Library.
 | |
|  *
 | |
|  *  Contains two exception-generating types (throw_value, throw_allocator)
 | |
|  *  intended to be used as value and allocator types while testing
 | |
|  *  exception safety in templatized containers and algorithms. The
 | |
|  *  allocator has additional log and debug features. The exception
 | |
|  *  generated is of type forced_exception_error.
 | |
|  */
 | |
| 
 | |
| #ifndef _THROW_ALLOCATOR_H
 | |
| #define _THROW_ALLOCATOR_H 1
 | |
| 
 | |
| #include <cmath>
 | |
| #include <ctime>
 | |
| #include <map>
 | |
| #include <string>
 | |
| #include <ostream>
 | |
| #include <stdexcept>
 | |
| #include <utility>
 | |
| #include <bits/functexcept.h>
 | |
| #include <bits/move.h>
 | |
| #if __cplusplus >= 201103L
 | |
| # include <functional>
 | |
| # include <random>
 | |
| #else
 | |
| # include <tr1/functional>
 | |
| # include <tr1/random>
 | |
| #endif
 | |
| 
 | |
| namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
 | |
| {
 | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION
 | |
| 
 | |
|   /**
 | |
|    *  @brief Thown by exception safety machinery.
 | |
|    *  @ingroup exceptions
 | |
|    */
 | |
|   struct forced_error : public std::exception
 | |
|   { };
 | |
| 
 | |
|   // Substitute for forced_error object when -fno-exceptions.
 | |
|   inline void
 | |
|   __throw_forced_error()
 | |
|   { _GLIBCXX_THROW_OR_ABORT(forced_error()); }
 | |
| 
 | |
|   /**
 | |
|    *  @brief Base class for checking address and label information
 | |
|    *  about allocations. Create a std::map between the allocated
 | |
|    *  address (void*) and a datum for annotations, which are a pair of
 | |
|    *  numbers corresponding to label and allocated size.
 | |
|    */
 | |
|   struct annotate_base
 | |
|   {
 | |
|     annotate_base()
 | |
|     {
 | |
|       label();
 | |
|       map_alloc();
 | |
|     }
 | |
| 
 | |
|     static void
 | |
|     set_label(size_t l)
 | |
|     { label() = l; }
 | |
| 
 | |
|     static size_t
 | |
|     get_label()
 | |
|     { return label(); }
 | |
| 
 | |
|     void
 | |
|     insert(void* p, size_t size)
 | |
|     {
 | |
|       if (!p)
 | |
| 	{
 | |
| 	  std::string error("annotate_base::insert null insert!\n");
 | |
| 	  log_to_string(error, make_entry(p, size));
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
| 
 | |
|       const_iterator found = map_alloc().find(p);
 | |
|       if (found != map_alloc().end())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::insert double insert!\n");
 | |
| 	  log_to_string(error, make_entry(p, size));
 | |
| 	  log_to_string(error, *found);
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
| 
 | |
|       map_alloc().insert(make_entry(p, size));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     erase(void* p, size_t size)
 | |
|     {
 | |
|       check_allocated(p, size);
 | |
|       map_alloc().erase(p);
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     void
 | |
|     insert_construct(void* p)
 | |
|     {
 | |
|       if (!p)
 | |
| 	{
 | |
| 	  std::string error("annotate_base::insert_construct null!\n");
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
| 
 | |
|       auto found = map_construct().find(p);
 | |
|       if (found != map_construct().end())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::insert_construct double insert!\n");
 | |
| 	  log_to_string(error, std::make_pair(p, get_label()));
 | |
| 	  log_to_string(error, *found);
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
| 
 | |
|       map_construct().insert(std::make_pair(p, get_label()));
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     erase_construct(void* p)
 | |
|     {
 | |
|       check_constructed(p);
 | |
|       map_construct().erase(p);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     // See if a particular address and allocation size has been saved.
 | |
|     inline void
 | |
|     check_allocated(void* p, size_t size)
 | |
|     {
 | |
|       const_iterator found = map_alloc().find(p);
 | |
|       if (found == map_alloc().end())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check_allocated by value "
 | |
| 			    "null erase!\n");
 | |
| 	  log_to_string(error, make_entry(p, size));
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
| 
 | |
|       if (found->second.second != size)
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check_allocated by value "
 | |
| 			    "wrong-size erase!\n");
 | |
| 	  log_to_string(error, make_entry(p, size));
 | |
| 	  log_to_string(error, *found);
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     // See if a given label has been allocated.
 | |
|     inline void
 | |
|     check(size_t label)
 | |
|     {
 | |
|       std::string found;
 | |
|       {
 | |
| 	const_iterator beg = map_alloc().begin();
 | |
| 	const_iterator end = map_alloc().end();
 | |
| 	while (beg != end)
 | |
| 	  {
 | |
| 	    if (beg->second.first == label)
 | |
| 	      log_to_string(found, *beg);
 | |
| 	    ++beg;
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       {
 | |
| 	auto beg = map_construct().begin();
 | |
| 	auto end = map_construct().end();
 | |
| 	while (beg != end)
 | |
| 	  {
 | |
| 	    if (beg->second == label)
 | |
| 	      log_to_string(found, *beg);
 | |
| 	    ++beg;
 | |
| 	  }
 | |
|       }
 | |
| #endif
 | |
| 
 | |
|       if (!found.empty())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check by label\n");
 | |
| 	  error += found;
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     // See if there is anything left allocated or constructed.
 | |
|     inline static void
 | |
|     check()
 | |
|     {
 | |
|       std::string found;
 | |
|       {
 | |
| 	const_iterator beg = map_alloc().begin();
 | |
| 	const_iterator end = map_alloc().end();
 | |
| 	while (beg != end)
 | |
| 	  {
 | |
| 	    log_to_string(found, *beg);
 | |
| 	    ++beg;
 | |
| 	  }
 | |
|       }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       {
 | |
| 	auto beg = map_construct().begin();
 | |
| 	auto end = map_construct().end();
 | |
| 	while (beg != end)
 | |
| 	  {
 | |
| 	    log_to_string(found, *beg);
 | |
| 	    ++beg;
 | |
| 	  }
 | |
|       }
 | |
| #endif
 | |
| 
 | |
|       if (!found.empty())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check \n");
 | |
| 	  error += found;
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     inline void
 | |
|     check_constructed(void* p)
 | |
|     {
 | |
|       auto found = map_construct().find(p);
 | |
|       if (found == map_construct().end())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check_constructed not "
 | |
| 			    "constructed!\n");
 | |
| 	  log_to_string(error, std::make_pair(p, get_label()));
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     inline void
 | |
|     check_constructed(size_t label)
 | |
|     {
 | |
|       auto beg = map_construct().begin();
 | |
|       auto end = map_construct().end();
 | |
|       std::string found;
 | |
|       while (beg != end)
 | |
| 	{
 | |
| 	  if (beg->second == label)
 | |
| 	    log_to_string(found, *beg);
 | |
| 	  ++beg;
 | |
| 	}
 | |
| 
 | |
|       if (!found.empty())
 | |
| 	{
 | |
| 	  std::string error("annotate_base::check_constructed by label\n");
 | |
| 	  error += found;
 | |
| 	  std::__throw_logic_error(error.c_str());
 | |
| 	}
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|   private:
 | |
|     typedef std::pair<size_t, size_t>		data_type;
 | |
|     typedef std::map<void*, data_type> 		map_alloc_type;
 | |
|     typedef map_alloc_type::value_type 		entry_type;
 | |
|     typedef map_alloc_type::const_iterator 		const_iterator;
 | |
|     typedef map_alloc_type::const_reference 		const_reference;
 | |
| #if __cplusplus >= 201103L
 | |
|     typedef std::map<void*, size_t>		map_construct_type;
 | |
| #endif
 | |
| 
 | |
|     friend std::ostream&
 | |
|     operator<<(std::ostream&, const annotate_base&);
 | |
| 
 | |
|     entry_type
 | |
|     make_entry(void* p, size_t size)
 | |
|     { return std::make_pair(p, data_type(get_label(), size)); }
 | |
| 
 | |
|     static void
 | |
|     log_to_string(std::string& s, const_reference ref)
 | |
|     {
 | |
|       char buf[40];
 | |
|       const char tab('\t');
 | |
|       s += "label: ";
 | |
|       unsigned long l = static_cast<unsigned long>(ref.second.first);
 | |
|       __builtin_sprintf(buf, "%lu", l);
 | |
|       s += buf;
 | |
|       s += tab;
 | |
|       s += "size: ";
 | |
|       l = static_cast<unsigned long>(ref.second.second);
 | |
|       __builtin_sprintf(buf, "%lu", l);
 | |
|       s += buf;
 | |
|       s += tab;
 | |
|       s += "address: ";
 | |
|       __builtin_sprintf(buf, "%p", ref.first);
 | |
|       s += buf;
 | |
|       s += '\n';
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     static void
 | |
|     log_to_string(std::string& s, const std::pair<const void*, size_t>& ref)
 | |
|     {
 | |
|       char buf[40];
 | |
|       const char tab('\t');
 | |
|       s += "label: ";
 | |
|       unsigned long l = static_cast<unsigned long>(ref.second);
 | |
|       __builtin_sprintf(buf, "%lu", l);
 | |
|       s += buf;
 | |
|       s += tab;
 | |
|       s += "address: ";
 | |
|       __builtin_sprintf(buf, "%p", ref.first);
 | |
|       s += buf;
 | |
|       s += '\n';
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     static size_t&
 | |
|     label()
 | |
|     {
 | |
|       static size_t _S_label(std::numeric_limits<size_t>::max());
 | |
|       return _S_label;
 | |
|     }
 | |
| 
 | |
|     static map_alloc_type&
 | |
|     map_alloc()
 | |
|     {
 | |
|       static map_alloc_type _S_map;
 | |
|       return _S_map;
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     static map_construct_type&
 | |
|     map_construct()
 | |
|     {
 | |
|       static map_construct_type _S_map;
 | |
|       return _S_map;
 | |
|     }
 | |
| #endif
 | |
|   };
 | |
| 
 | |
|   inline std::ostream&
 | |
|   operator<<(std::ostream& os, const annotate_base& __b)
 | |
|   {
 | |
|     std::string error;
 | |
|     typedef annotate_base base_type;
 | |
|     {
 | |
|       base_type::const_iterator beg = __b.map_alloc().begin();
 | |
|       base_type::const_iterator end = __b.map_alloc().end();
 | |
|       for (; beg != end; ++beg)
 | |
| 	__b.log_to_string(error, *beg);
 | |
|     }
 | |
| #if __cplusplus >= 201103L
 | |
|     {
 | |
|       auto beg = __b.map_construct().begin();
 | |
|       auto end = __b.map_construct().end();
 | |
|       for (; beg != end; ++beg)
 | |
| 	__b.log_to_string(error, *beg);      
 | |
|     }
 | |
| #endif
 | |
|     return os << error;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    *  @brief Base struct for condition policy.
 | |
|    *
 | |
|    * Requires a public member function with the signature
 | |
|    * void throw_conditionally()
 | |
|    */
 | |
|   struct condition_base
 | |
|   {
 | |
|     virtual ~condition_base() { };
 | |
|   };
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    *  @brief Base class for incremental control and throw.
 | |
|    */
 | |
|   struct limit_condition : public condition_base
 | |
|   {
 | |
|     // Scope-level adjustor objects: set limit for throw at the
 | |
|     // beginning of a scope block, and restores to previous limit when
 | |
|     // object is destroyed on exiting the block.
 | |
|     struct adjustor_base
 | |
|     {
 | |
|     private:
 | |
|       const size_t _M_orig;
 | |
| 
 | |
|     public:
 | |
|       adjustor_base() : _M_orig(limit()) { }
 | |
| 
 | |
|       virtual
 | |
|       ~adjustor_base() { set_limit(_M_orig); }
 | |
|     };
 | |
| 
 | |
|     /// Never enter the condition.
 | |
|     struct never_adjustor : public adjustor_base
 | |
|     {
 | |
|       never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); }
 | |
|     };
 | |
| 
 | |
|     /// Always enter the condition.
 | |
|     struct always_adjustor : public adjustor_base
 | |
|     {
 | |
|       always_adjustor() { set_limit(count()); }
 | |
|     };
 | |
| 
 | |
|     /// Enter the nth condition.
 | |
|     struct limit_adjustor : public adjustor_base
 | |
|     {
 | |
|       limit_adjustor(const size_t __l) { set_limit(__l); }
 | |
|     };
 | |
| 
 | |
|     // Increment _S_count every time called.
 | |
|     // If _S_count matches the limit count, throw.
 | |
|     static void
 | |
|     throw_conditionally()
 | |
|     {
 | |
|       if (count() == limit())
 | |
| 	__throw_forced_error();
 | |
|       ++count();
 | |
|     }
 | |
| 
 | |
|     static size_t&
 | |
|     count()
 | |
|     {
 | |
|       static size_t _S_count(0);
 | |
|       return _S_count;
 | |
|     }
 | |
| 
 | |
|     static size_t&
 | |
|     limit()
 | |
|     {
 | |
|       static size_t _S_limit(std::numeric_limits<size_t>::max());
 | |
|       return _S_limit;
 | |
|     }
 | |
| 
 | |
|     // Zero the throw counter, set limit to argument.
 | |
|     static void
 | |
|     set_limit(const size_t __l)
 | |
|     {
 | |
|       limit() = __l;
 | |
|       count() = 0;
 | |
|     }
 | |
|   };
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    *  @brief Base class for random probability control and throw.
 | |
|    */
 | |
|   struct random_condition : public condition_base
 | |
|   {
 | |
|     // Scope-level adjustor objects: set probability for throw at the
 | |
|     // beginning of a scope block, and restores to previous
 | |
|     // probability when object is destroyed on exiting the block.
 | |
|     struct adjustor_base
 | |
|     {
 | |
|     private:
 | |
|       const double _M_orig;
 | |
| 
 | |
|     public:
 | |
|       adjustor_base() : _M_orig(probability()) { }
 | |
| 
 | |
|       virtual ~adjustor_base()
 | |
|       { set_probability(_M_orig); }
 | |
|     };
 | |
| 
 | |
|     /// Group condition.
 | |
|     struct group_adjustor : public adjustor_base
 | |
|     {
 | |
|       group_adjustor(size_t size)
 | |
|       { set_probability(1 - std::pow(double(1 - probability()),
 | |
| 				     double(0.5 / (size + 1))));
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     /// Never enter the condition.
 | |
|     struct never_adjustor : public adjustor_base
 | |
|     {
 | |
|       never_adjustor() { set_probability(0); }
 | |
|     };
 | |
| 
 | |
|     /// Always enter the condition.
 | |
|     struct always_adjustor : public adjustor_base
 | |
|     {
 | |
|       always_adjustor() { set_probability(1); }
 | |
|     };
 | |
| 
 | |
|     random_condition()
 | |
|     {
 | |
|       probability();
 | |
|       engine();
 | |
|     }
 | |
| 
 | |
|     static void
 | |
|     set_probability(double __p)
 | |
|     { probability() = __p; }
 | |
| 
 | |
|     static void
 | |
|     throw_conditionally()
 | |
|     {
 | |
|       if (generate() < probability())
 | |
| 	__throw_forced_error();
 | |
|     }
 | |
| 
 | |
|     void
 | |
|     seed(unsigned long __s)
 | |
|     { engine().seed(__s); }
 | |
| 
 | |
|   private:
 | |
| #if __cplusplus >= 201103L
 | |
|     typedef std::uniform_real_distribution<double> 	distribution_type;
 | |
|     typedef std::mt19937 				engine_type;
 | |
| #else
 | |
|     typedef std::tr1::uniform_real<double> 		distribution_type;
 | |
|     typedef std::tr1::mt19937 				engine_type;
 | |
| #endif
 | |
| 
 | |
|     static double
 | |
|     generate()
 | |
|     {
 | |
| #if __cplusplus >= 201103L
 | |
|       const distribution_type distribution(0, 1);
 | |
|       static auto generator = std::bind(distribution, engine());
 | |
| #else
 | |
|       // Use variate_generator to get normalized results.
 | |
|       typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t;
 | |
|       distribution_type distribution(0, 1);
 | |
|       static gen_t generator(engine(), distribution);
 | |
| #endif
 | |
| 
 | |
|       double random = generator();
 | |
|       if (random < distribution.min() || random > distribution.max())
 | |
| 	{
 | |
| 	  std::string __s("random_condition::generate");
 | |
| 	  __s += "\n";
 | |
| 	  __s += "random number generated is: ";
 | |
| 	  char buf[40];
 | |
| 	  __builtin_sprintf(buf, "%f", random);
 | |
| 	  __s += buf;
 | |
| 	  std::__throw_out_of_range(__s.c_str());
 | |
| 	}
 | |
| 
 | |
|       return random;
 | |
|     }
 | |
| 
 | |
|     static double&
 | |
|     probability()
 | |
|     {
 | |
|       static double _S_p;
 | |
|       return _S_p;
 | |
|     }
 | |
| 
 | |
|     static engine_type&
 | |
|     engine()
 | |
|     {
 | |
|       static engine_type _S_e;
 | |
|       return _S_e;
 | |
|     }
 | |
|   };
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    *  @brief Class with exception generation control. Intended to be
 | |
|    *  used as a value_type in templatized code.
 | |
|    *
 | |
|    *  Note: Destructor not allowed to throw.
 | |
|    */
 | |
|   template<typename _Cond>
 | |
|     struct throw_value_base : public _Cond
 | |
|     {
 | |
|       typedef _Cond  				condition_type;
 | |
| 
 | |
|       using condition_type::throw_conditionally;
 | |
| 
 | |
|       std::size_t			       	_M_i;
 | |
| 
 | |
| #ifndef _GLIBCXX_IS_AGGREGATE
 | |
|       throw_value_base() : _M_i(0)
 | |
|       { throw_conditionally(); }
 | |
| 
 | |
|       throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i)
 | |
|       { throw_conditionally(); }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       // Shall not throw.
 | |
|       throw_value_base(throw_value_base&&) = default;
 | |
| #endif
 | |
| 
 | |
|       explicit throw_value_base(const std::size_t __i) : _M_i(__i)
 | |
|       { throw_conditionally(); }
 | |
| #endif
 | |
| 
 | |
|       throw_value_base&
 | |
|       operator=(const throw_value_base& __v)
 | |
|       {
 | |
| 	throw_conditionally();
 | |
| 	_M_i = __v._M_i;
 | |
| 	return *this;
 | |
|       }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       // Shall not throw.
 | |
|       throw_value_base&
 | |
|       operator=(throw_value_base&&) = default;
 | |
| #endif
 | |
| 
 | |
|       throw_value_base&
 | |
|       operator++()
 | |
|       {
 | |
| 	throw_conditionally();
 | |
| 	++_M_i;
 | |
| 	return *this;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|   template<typename _Cond>
 | |
|     inline void
 | |
|     swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       throw_value orig(__a);
 | |
|       __a = __b;
 | |
|       __b = orig;
 | |
|     }
 | |
| 
 | |
|   // General instantiable types requirements.
 | |
|   template<typename _Cond>
 | |
|     inline bool
 | |
|     operator==(const throw_value_base<_Cond>& __a,
 | |
| 	       const throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       bool __ret = __a._M_i == __b._M_i;
 | |
|       return __ret;
 | |
|     }
 | |
| 
 | |
|   template<typename _Cond>
 | |
|     inline bool
 | |
|     operator<(const throw_value_base<_Cond>& __a,
 | |
| 	      const throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       bool __ret = __a._M_i < __b._M_i;
 | |
|       return __ret;
 | |
|     }
 | |
| 
 | |
|   // Numeric algorithms instantiable types requirements.
 | |
|   template<typename _Cond>
 | |
|     inline throw_value_base<_Cond>
 | |
|     operator+(const throw_value_base<_Cond>& __a,
 | |
| 	      const throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       throw_value __ret(__a._M_i + __b._M_i);
 | |
|       return __ret;
 | |
|     }
 | |
| 
 | |
|   template<typename _Cond>
 | |
|     inline throw_value_base<_Cond>
 | |
|     operator-(const throw_value_base<_Cond>& __a,
 | |
| 	      const throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       throw_value __ret(__a._M_i - __b._M_i);
 | |
|       return __ret;
 | |
|     }
 | |
| 
 | |
|   template<typename _Cond>
 | |
|     inline throw_value_base<_Cond>
 | |
|     operator*(const throw_value_base<_Cond>& __a,
 | |
| 	      const throw_value_base<_Cond>& __b)
 | |
|     {
 | |
|       typedef throw_value_base<_Cond> throw_value;
 | |
|       throw_value::throw_conditionally();
 | |
|       throw_value __ret(__a._M_i * __b._M_i);
 | |
|       return __ret;
 | |
|     }
 | |
| 
 | |
| 
 | |
|   /// Type throwing via limit condition.
 | |
|   struct throw_value_limit : public throw_value_base<limit_condition>
 | |
|   {
 | |
|     typedef throw_value_base<limit_condition> base_type;
 | |
| 
 | |
| #ifndef _GLIBCXX_IS_AGGREGATE
 | |
|     throw_value_limit() { }
 | |
| 
 | |
|     throw_value_limit(const throw_value_limit& __other)
 | |
|     : base_type(__other._M_i) { }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     throw_value_limit(throw_value_limit&&) = default;
 | |
| #endif
 | |
| 
 | |
|     explicit throw_value_limit(const std::size_t __i) : base_type(__i) { }
 | |
| #endif
 | |
| 
 | |
|     throw_value_limit&
 | |
|     operator=(const throw_value_limit& __other)
 | |
|     {
 | |
|       base_type::operator=(__other);
 | |
|       return *this;
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     throw_value_limit&
 | |
|     operator=(throw_value_limit&&) = default;
 | |
| #endif
 | |
|   };
 | |
| 
 | |
|   /// Type throwing via random condition.
 | |
|   struct throw_value_random : public throw_value_base<random_condition>
 | |
|   {
 | |
|     typedef throw_value_base<random_condition> base_type;
 | |
| 
 | |
| #ifndef _GLIBCXX_IS_AGGREGATE
 | |
|     throw_value_random() { }
 | |
| 
 | |
|     throw_value_random(const throw_value_random& __other)
 | |
|     : base_type(__other._M_i) { }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     throw_value_random(throw_value_random&&) = default;
 | |
| #endif
 | |
| 
 | |
|     explicit throw_value_random(const std::size_t __i) : base_type(__i) { }
 | |
| #endif
 | |
| 
 | |
|     throw_value_random&
 | |
|     operator=(const throw_value_random& __other)
 | |
|     {
 | |
|       base_type::operator=(__other);
 | |
|       return *this;
 | |
|     }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|     throw_value_random&
 | |
|     operator=(throw_value_random&&) = default;
 | |
| #endif
 | |
|   };
 | |
| 
 | |
| 
 | |
|   /**
 | |
|    *  @brief Allocator class with logging and exception generation control.
 | |
|    * Intended to be used as an allocator_type in templatized code.
 | |
|    *  @ingroup allocators
 | |
|    *
 | |
|    *  Note: Deallocate not allowed to throw.
 | |
|    */
 | |
|   template<typename _Tp, typename _Cond>
 | |
|     class throw_allocator_base
 | |
|     : public annotate_base, public _Cond
 | |
|     {
 | |
|     public:
 | |
|       typedef size_t 				size_type;
 | |
|       typedef ptrdiff_t 			difference_type;
 | |
|       typedef _Tp 				value_type;
 | |
|       typedef value_type* 			pointer;
 | |
|       typedef const value_type* 		const_pointer;
 | |
|       typedef value_type& 			reference;
 | |
|       typedef const value_type& 		const_reference;
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       // _GLIBCXX_RESOLVE_LIB_DEFECTS
 | |
|       // 2103. std::allocator propagate_on_container_move_assignment
 | |
|       typedef std::true_type propagate_on_container_move_assignment;
 | |
| #endif
 | |
| 
 | |
|     private:
 | |
|       typedef _Cond				condition_type;
 | |
| 
 | |
|       std::allocator<value_type> 		_M_allocator;
 | |
| 
 | |
|       using condition_type::throw_conditionally;
 | |
| 
 | |
|     public:
 | |
|       size_type
 | |
|       max_size() const _GLIBCXX_USE_NOEXCEPT
 | |
|       { return _M_allocator.max_size(); }
 | |
| 
 | |
|       pointer
 | |
|       address(reference __x) const _GLIBCXX_NOEXCEPT
 | |
|       { return std::__addressof(__x); }
 | |
| 
 | |
|       const_pointer
 | |
|       address(const_reference __x) const _GLIBCXX_NOEXCEPT
 | |
|       { return std::__addressof(__x); }
 | |
| 
 | |
|       pointer
 | |
|       allocate(size_type __n, std::allocator<void>::const_pointer hint = 0)
 | |
|       {
 | |
| 	if (__n > this->max_size())
 | |
| 	  std::__throw_bad_alloc();
 | |
| 
 | |
| 	throw_conditionally();
 | |
| 	pointer const a = _M_allocator.allocate(__n, hint);
 | |
| 	insert(a, sizeof(value_type) * __n);
 | |
| 	return a;
 | |
|       }
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
|       template<typename _Up, typename... _Args>
 | |
|         void
 | |
|         construct(_Up* __p, _Args&&... __args)
 | |
| 	{
 | |
| 	  _M_allocator.construct(__p, std::forward<_Args>(__args)...);
 | |
| 	  insert_construct(__p);
 | |
| 	}
 | |
| 
 | |
|       template<typename _Up>
 | |
|         void 
 | |
|         destroy(_Up* __p)
 | |
|         {
 | |
| 	  erase_construct(__p);
 | |
| 	  _M_allocator.destroy(__p);
 | |
| 	}
 | |
| #else
 | |
|       void
 | |
|       construct(pointer __p, const value_type& val)
 | |
|       { return _M_allocator.construct(__p, val); }
 | |
| 
 | |
|       void
 | |
|       destroy(pointer __p)
 | |
|       { _M_allocator.destroy(__p); }
 | |
| #endif
 | |
| 
 | |
|       void
 | |
|       deallocate(pointer __p, size_type __n)
 | |
|       {
 | |
| 	erase(__p, sizeof(value_type) * __n);
 | |
| 	_M_allocator.deallocate(__p, __n);
 | |
|       }
 | |
| 
 | |
|       void
 | |
|       check_allocated(pointer __p, size_type __n)
 | |
|       {
 | |
| 	size_type __t = sizeof(value_type) * __n;
 | |
| 	annotate_base::check_allocated(__p, __t);
 | |
|       }
 | |
| 
 | |
|       void
 | |
|       check(size_type __n)
 | |
|       { annotate_base::check(__n); }
 | |
|   };
 | |
| 
 | |
|   template<typename _Tp, typename _Cond>
 | |
|     inline bool
 | |
|     operator==(const throw_allocator_base<_Tp, _Cond>&,
 | |
| 	       const throw_allocator_base<_Tp, _Cond>&)
 | |
|     { return true; }
 | |
| 
 | |
|   template<typename _Tp, typename _Cond>
 | |
|     inline bool
 | |
|     operator!=(const throw_allocator_base<_Tp, _Cond>&,
 | |
| 	       const throw_allocator_base<_Tp, _Cond>&)
 | |
|     { return false; }
 | |
| 
 | |
|   /// Allocator throwing via limit condition.
 | |
|   template<typename _Tp>
 | |
|     struct throw_allocator_limit
 | |
|     : public throw_allocator_base<_Tp, limit_condition>
 | |
|     {
 | |
|       template<typename _Tp1>
 | |
| 	struct rebind
 | |
| 	{ typedef throw_allocator_limit<_Tp1> other; };
 | |
| 
 | |
|       throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       throw_allocator_limit(const throw_allocator_limit&)
 | |
|       _GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       template<typename _Tp1>
 | |
| 	throw_allocator_limit(const throw_allocator_limit<_Tp1>&)
 | |
| 	_GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
 | |
|     };
 | |
| 
 | |
|   /// Allocator throwing via random condition.
 | |
|   template<typename _Tp>
 | |
|     struct throw_allocator_random
 | |
|     : public throw_allocator_base<_Tp, random_condition>
 | |
|     {
 | |
|       template<typename _Tp1>
 | |
| 	struct rebind
 | |
| 	{ typedef throw_allocator_random<_Tp1> other; };
 | |
| 
 | |
|       throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       throw_allocator_random(const throw_allocator_random&)
 | |
|       _GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       template<typename _Tp1>
 | |
| 	throw_allocator_random(const throw_allocator_random<_Tp1>&)
 | |
| 	_GLIBCXX_USE_NOEXCEPT { }
 | |
| 
 | |
|       ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
 | |
|     };
 | |
| 
 | |
| _GLIBCXX_END_NAMESPACE_VERSION
 | |
| } // namespace
 | |
| 
 | |
| #if __cplusplus >= 201103L
 | |
| 
 | |
| # include <bits/functional_hash.h>
 | |
| 
 | |
| namespace std _GLIBCXX_VISIBILITY(default)
 | |
| {
 | |
|   /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit.
 | |
|   template<>
 | |
|     struct hash<__gnu_cxx::throw_value_limit>
 | |
|     : public std::unary_function<__gnu_cxx::throw_value_limit, size_t>
 | |
|     {
 | |
|       size_t
 | |
|       operator()(const __gnu_cxx::throw_value_limit& __val) const
 | |
|       {
 | |
| 	__gnu_cxx::throw_value_limit::throw_conditionally();
 | |
| 	std::hash<std::size_t> __h;
 | |
| 	size_t __result = __h(__val._M_i);
 | |
| 	return __result;
 | |
|       }
 | |
|     };
 | |
| 
 | |
|   /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random.
 | |
|   template<>
 | |
|     struct hash<__gnu_cxx::throw_value_random>
 | |
|     : public std::unary_function<__gnu_cxx::throw_value_random, size_t>
 | |
|     {
 | |
|       size_t
 | |
|       operator()(const __gnu_cxx::throw_value_random& __val) const
 | |
|       {
 | |
| 	__gnu_cxx::throw_value_random::throw_conditionally();
 | |
| 	std::hash<std::size_t> __h;
 | |
| 	size_t __result = __h(__val._M_i);
 | |
| 	return __result;
 | |
|       }
 | |
|     };
 | |
| } // end namespace std
 | |
| #endif
 | |
| 
 | |
| #endif
 |