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