1// -*- C++ -*-
2
3// Copyright (C) 2005-2015 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
66namespace __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
946namespace 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