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