source: Daodan/MSYS2/mingw32/include/c++/11.2.0/ext/throw_allocator.h@ 1170

Last change on this file since 1170 was 1166, checked in by rossy, 3 years ago

Daodan: Replace MinGW build env with an up-to-date MSYS2 env

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