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