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