libstdc++
|
00001 // -*- C++ -*- 00002 00003 // Copyright (C) 2005-2015 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the terms 00007 // of the GNU General Public License as published by the Free Software 00008 // Foundation; either version 3, or (at your option) any later 00009 // version. 00010 00011 // This library is distributed in the hope that it will be useful, but 00012 // WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 00026 00027 // Permission to use, copy, modify, sell, and distribute this software 00028 // is hereby granted without fee, provided that the above copyright 00029 // notice appears in all copies, and that both that copyright notice 00030 // and this permission notice appear in supporting documentation. None 00031 // of the above authors, nor IBM Haifa Research Laboratories, make any 00032 // representation about the suitability of this software for any 00033 // purpose. It is provided "as is" without express or implied 00034 // warranty. 00035 00036 /** @file ext/throw_allocator.h 00037 * This file is a GNU extension to the Standard C++ Library. 00038 * 00039 * Contains two exception-generating types (throw_value, throw_allocator) 00040 * intended to be used as value and allocator types while testing 00041 * exception safety in templatized containers and algorithms. The 00042 * allocator has additional log and debug features. The exception 00043 * generated is of type forced_exception_error. 00044 */ 00045 00046 #ifndef _THROW_ALLOCATOR_H 00047 #define _THROW_ALLOCATOR_H 1 00048 00049 #include <cmath> 00050 #include <ctime> 00051 #include <map> 00052 #include <string> 00053 #include <ostream> 00054 #include <stdexcept> 00055 #include <utility> 00056 #include <bits/functexcept.h> 00057 #include <bits/move.h> 00058 #if __cplusplus >= 201103L 00059 # include <functional> 00060 # include <random> 00061 #else 00062 # include <tr1/functional> 00063 # include <tr1/random> 00064 #endif 00065 00066 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 00067 { 00068 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00069 00070 /** 00071 * @brief Thown by exception safety machinery. 00072 * @ingroup exceptions 00073 */ 00074 struct forced_error : public std::exception 00075 { }; 00076 00077 // Substitute for forced_error object when -fno-exceptions. 00078 inline void 00079 __throw_forced_error() 00080 { _GLIBCXX_THROW_OR_ABORT(forced_error()); } 00081 00082 /** 00083 * @brief Base class for checking address and label information 00084 * about allocations. Create a std::map between the allocated 00085 * address (void*) and a datum for annotations, which are a pair of 00086 * numbers corresponding to label and allocated size. 00087 */ 00088 struct annotate_base 00089 { 00090 annotate_base() 00091 { 00092 label(); 00093 map_alloc(); 00094 } 00095 00096 static void 00097 set_label(size_t l) 00098 { label() = l; } 00099 00100 static size_t 00101 get_label() 00102 { return label(); } 00103 00104 void 00105 insert(void* p, size_t size) 00106 { 00107 if (!p) 00108 { 00109 std::string error("annotate_base::insert null insert!\n"); 00110 log_to_string(error, make_entry(p, size)); 00111 std::__throw_logic_error(error.c_str()); 00112 } 00113 00114 const_iterator found = map_alloc().find(p); 00115 if (found != map_alloc().end()) 00116 { 00117 std::string error("annotate_base::insert double insert!\n"); 00118 log_to_string(error, make_entry(p, size)); 00119 log_to_string(error, *found); 00120 std::__throw_logic_error(error.c_str()); 00121 } 00122 00123 map_alloc().insert(make_entry(p, size)); 00124 } 00125 00126 void 00127 erase(void* p, size_t size) 00128 { 00129 check_allocated(p, size); 00130 map_alloc().erase(p); 00131 } 00132 00133 #if __cplusplus >= 201103L 00134 void 00135 insert_construct(void* p) 00136 { 00137 if (!p) 00138 { 00139 std::string error("annotate_base::insert_construct null!\n"); 00140 std::__throw_logic_error(error.c_str()); 00141 } 00142 00143 auto found = map_construct().find(p); 00144 if (found != map_construct().end()) 00145 { 00146 std::string error("annotate_base::insert_construct double insert!\n"); 00147 log_to_string(error, std::make_pair(p, get_label())); 00148 log_to_string(error, *found); 00149 std::__throw_logic_error(error.c_str()); 00150 } 00151 00152 map_construct().insert(std::make_pair(p, get_label())); 00153 } 00154 00155 void 00156 erase_construct(void* p) 00157 { 00158 check_constructed(p); 00159 map_construct().erase(p); 00160 } 00161 #endif 00162 00163 // See if a particular address and allocation size has been saved. 00164 inline void 00165 check_allocated(void* p, size_t size) 00166 { 00167 const_iterator found = map_alloc().find(p); 00168 if (found == map_alloc().end()) 00169 { 00170 std::string error("annotate_base::check_allocated by value " 00171 "null erase!\n"); 00172 log_to_string(error, make_entry(p, size)); 00173 std::__throw_logic_error(error.c_str()); 00174 } 00175 00176 if (found->second.second != size) 00177 { 00178 std::string error("annotate_base::check_allocated by value " 00179 "wrong-size erase!\n"); 00180 log_to_string(error, make_entry(p, size)); 00181 log_to_string(error, *found); 00182 std::__throw_logic_error(error.c_str()); 00183 } 00184 } 00185 00186 // See if a given label has been allocated. 00187 inline void 00188 check(size_t label) 00189 { 00190 std::string found; 00191 { 00192 const_iterator beg = map_alloc().begin(); 00193 const_iterator end = map_alloc().end(); 00194 while (beg != end) 00195 { 00196 if (beg->second.first == label) 00197 log_to_string(found, *beg); 00198 ++beg; 00199 } 00200 } 00201 00202 #if __cplusplus >= 201103L 00203 { 00204 auto beg = map_construct().begin(); 00205 auto end = map_construct().end(); 00206 while (beg != end) 00207 { 00208 if (beg->second == label) 00209 log_to_string(found, *beg); 00210 ++beg; 00211 } 00212 } 00213 #endif 00214 00215 if (!found.empty()) 00216 { 00217 std::string error("annotate_base::check by label\n"); 00218 error += found; 00219 std::__throw_logic_error(error.c_str()); 00220 } 00221 } 00222 00223 // See if there is anything left allocated or constructed. 00224 inline static void 00225 check() 00226 { 00227 std::string found; 00228 { 00229 const_iterator beg = map_alloc().begin(); 00230 const_iterator end = map_alloc().end(); 00231 while (beg != end) 00232 { 00233 log_to_string(found, *beg); 00234 ++beg; 00235 } 00236 } 00237 00238 #if __cplusplus >= 201103L 00239 { 00240 auto beg = map_construct().begin(); 00241 auto end = map_construct().end(); 00242 while (beg != end) 00243 { 00244 log_to_string(found, *beg); 00245 ++beg; 00246 } 00247 } 00248 #endif 00249 00250 if (!found.empty()) 00251 { 00252 std::string error("annotate_base::check \n"); 00253 error += found; 00254 std::__throw_logic_error(error.c_str()); 00255 } 00256 } 00257 00258 #if __cplusplus >= 201103L 00259 inline void 00260 check_constructed(void* p) 00261 { 00262 auto found = map_construct().find(p); 00263 if (found == map_construct().end()) 00264 { 00265 std::string error("annotate_base::check_constructed not " 00266 "constructed!\n"); 00267 log_to_string(error, std::make_pair(p, get_label())); 00268 std::__throw_logic_error(error.c_str()); 00269 } 00270 } 00271 00272 inline void 00273 check_constructed(size_t label) 00274 { 00275 auto beg = map_construct().begin(); 00276 auto end = map_construct().end(); 00277 std::string found; 00278 while (beg != end) 00279 { 00280 if (beg->second == label) 00281 log_to_string(found, *beg); 00282 ++beg; 00283 } 00284 00285 if (!found.empty()) 00286 { 00287 std::string error("annotate_base::check_constructed by label\n"); 00288 error += found; 00289 std::__throw_logic_error(error.c_str()); 00290 } 00291 } 00292 #endif 00293 00294 private: 00295 typedef std::pair<size_t, size_t> data_type; 00296 typedef std::map<void*, data_type> map_alloc_type; 00297 typedef map_alloc_type::value_type entry_type; 00298 typedef map_alloc_type::const_iterator const_iterator; 00299 typedef map_alloc_type::const_reference const_reference; 00300 #if __cplusplus >= 201103L 00301 typedef std::map<void*, size_t> map_construct_type; 00302 #endif 00303 00304 friend std::ostream& 00305 operator<<(std::ostream&, const annotate_base&); 00306 00307 entry_type 00308 make_entry(void* p, size_t size) 00309 { return std::make_pair(p, data_type(get_label(), size)); } 00310 00311 static void 00312 log_to_string(std::string& s, const_reference ref) 00313 { 00314 char buf[40]; 00315 const char tab('\t'); 00316 s += "label: "; 00317 unsigned long l = static_cast<unsigned long>(ref.second.first); 00318 __builtin_sprintf(buf, "%lu", l); 00319 s += buf; 00320 s += tab; 00321 s += "size: "; 00322 l = static_cast<unsigned long>(ref.second.second); 00323 __builtin_sprintf(buf, "%lu", l); 00324 s += buf; 00325 s += tab; 00326 s += "address: "; 00327 __builtin_sprintf(buf, "%p", ref.first); 00328 s += buf; 00329 s += '\n'; 00330 } 00331 00332 #if __cplusplus >= 201103L 00333 static void 00334 log_to_string(std::string& s, const std::pair<const void*, size_t>& ref) 00335 { 00336 char buf[40]; 00337 const char tab('\t'); 00338 s += "label: "; 00339 unsigned long l = static_cast<unsigned long>(ref.second); 00340 __builtin_sprintf(buf, "%lu", l); 00341 s += buf; 00342 s += tab; 00343 s += "address: "; 00344 __builtin_sprintf(buf, "%p", ref.first); 00345 s += buf; 00346 s += '\n'; 00347 } 00348 #endif 00349 00350 static size_t& 00351 label() 00352 { 00353 static size_t _S_label(std::numeric_limits<size_t>::max()); 00354 return _S_label; 00355 } 00356 00357 static map_alloc_type& 00358 map_alloc() 00359 { 00360 static map_alloc_type _S_map; 00361 return _S_map; 00362 } 00363 00364 #if __cplusplus >= 201103L 00365 static map_construct_type& 00366 map_construct() 00367 { 00368 static map_construct_type _S_map; 00369 return _S_map; 00370 } 00371 #endif 00372 }; 00373 00374 inline std::ostream& 00375 operator<<(std::ostream& os, const annotate_base& __b) 00376 { 00377 std::string error; 00378 typedef annotate_base base_type; 00379 { 00380 base_type::const_iterator beg = __b.map_alloc().begin(); 00381 base_type::const_iterator end = __b.map_alloc().end(); 00382 for (; beg != end; ++beg) 00383 __b.log_to_string(error, *beg); 00384 } 00385 #if __cplusplus >= 201103L 00386 { 00387 auto beg = __b.map_construct().begin(); 00388 auto end = __b.map_construct().end(); 00389 for (; beg != end; ++beg) 00390 __b.log_to_string(error, *beg); 00391 } 00392 #endif 00393 return os << error; 00394 } 00395 00396 00397 /** 00398 * @brief Base struct for condition policy. 00399 * 00400 * Requires a public member function with the signature 00401 * void throw_conditionally() 00402 */ 00403 struct condition_base 00404 { 00405 virtual ~condition_base() { }; 00406 }; 00407 00408 00409 /** 00410 * @brief Base class for incremental control and throw. 00411 */ 00412 struct limit_condition : public condition_base 00413 { 00414 // Scope-level adjustor objects: set limit for throw at the 00415 // beginning of a scope block, and restores to previous limit when 00416 // object is destroyed on exiting the block. 00417 struct adjustor_base 00418 { 00419 private: 00420 const size_t _M_orig; 00421 00422 public: 00423 adjustor_base() : _M_orig(limit()) { } 00424 00425 virtual 00426 ~adjustor_base() { set_limit(_M_orig); } 00427 }; 00428 00429 /// Never enter the condition. 00430 struct never_adjustor : public adjustor_base 00431 { 00432 never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); } 00433 }; 00434 00435 /// Always enter the condition. 00436 struct always_adjustor : public adjustor_base 00437 { 00438 always_adjustor() { set_limit(count()); } 00439 }; 00440 00441 /// Enter the nth condition. 00442 struct limit_adjustor : public adjustor_base 00443 { 00444 limit_adjustor(const size_t __l) { set_limit(__l); } 00445 }; 00446 00447 // Increment _S_count every time called. 00448 // If _S_count matches the limit count, throw. 00449 static void 00450 throw_conditionally() 00451 { 00452 if (count() == limit()) 00453 __throw_forced_error(); 00454 ++count(); 00455 } 00456 00457 static size_t& 00458 count() 00459 { 00460 static size_t _S_count(0); 00461 return _S_count; 00462 } 00463 00464 static size_t& 00465 limit() 00466 { 00467 static size_t _S_limit(std::numeric_limits<size_t>::max()); 00468 return _S_limit; 00469 } 00470 00471 // Zero the throw counter, set limit to argument. 00472 static void 00473 set_limit(const size_t __l) 00474 { 00475 limit() = __l; 00476 count() = 0; 00477 } 00478 }; 00479 00480 00481 /** 00482 * @brief Base class for random probability control and throw. 00483 */ 00484 struct random_condition : public condition_base 00485 { 00486 // Scope-level adjustor objects: set probability for throw at the 00487 // beginning of a scope block, and restores to previous 00488 // probability when object is destroyed on exiting the block. 00489 struct adjustor_base 00490 { 00491 private: 00492 const double _M_orig; 00493 00494 public: 00495 adjustor_base() : _M_orig(probability()) { } 00496 00497 virtual ~adjustor_base() 00498 { set_probability(_M_orig); } 00499 }; 00500 00501 /// Group condition. 00502 struct group_adjustor : public adjustor_base 00503 { 00504 group_adjustor(size_t size) 00505 { set_probability(1 - std::pow(double(1 - probability()), 00506 double(0.5 / (size + 1)))); 00507 } 00508 }; 00509 00510 /// Never enter the condition. 00511 struct never_adjustor : public adjustor_base 00512 { 00513 never_adjustor() { set_probability(0); } 00514 }; 00515 00516 /// Always enter the condition. 00517 struct always_adjustor : public adjustor_base 00518 { 00519 always_adjustor() { set_probability(1); } 00520 }; 00521 00522 random_condition() 00523 { 00524 probability(); 00525 engine(); 00526 } 00527 00528 static void 00529 set_probability(double __p) 00530 { probability() = __p; } 00531 00532 static void 00533 throw_conditionally() 00534 { 00535 if (generate() < probability()) 00536 __throw_forced_error(); 00537 } 00538 00539 void 00540 seed(unsigned long __s) 00541 { engine().seed(__s); } 00542 00543 private: 00544 #if __cplusplus >= 201103L 00545 typedef std::uniform_real_distribution<double> distribution_type; 00546 typedef std::mt19937 engine_type; 00547 #else 00548 typedef std::tr1::uniform_real<double> distribution_type; 00549 typedef std::tr1::mt19937 engine_type; 00550 #endif 00551 00552 static double 00553 generate() 00554 { 00555 #if __cplusplus >= 201103L 00556 const distribution_type distribution(0, 1); 00557 static auto generator = std::bind(distribution, engine()); 00558 #else 00559 // Use variate_generator to get normalized results. 00560 typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t; 00561 distribution_type distribution(0, 1); 00562 static gen_t generator(engine(), distribution); 00563 #endif 00564 00565 double random = generator(); 00566 if (random < distribution.min() || random > distribution.max()) 00567 { 00568 std::string __s("random_condition::generate"); 00569 __s += "\n"; 00570 __s += "random number generated is: "; 00571 char buf[40]; 00572 __builtin_sprintf(buf, "%f", random); 00573 __s += buf; 00574 std::__throw_out_of_range(__s.c_str()); 00575 } 00576 00577 return random; 00578 } 00579 00580 static double& 00581 probability() 00582 { 00583 static double _S_p; 00584 return _S_p; 00585 } 00586 00587 static engine_type& 00588 engine() 00589 { 00590 static engine_type _S_e; 00591 return _S_e; 00592 } 00593 }; 00594 00595 00596 /** 00597 * @brief Class with exception generation control. Intended to be 00598 * used as a value_type in templatized code. 00599 * 00600 * Note: Destructor not allowed to throw. 00601 */ 00602 template<typename _Cond> 00603 struct throw_value_base : public _Cond 00604 { 00605 typedef _Cond condition_type; 00606 00607 using condition_type::throw_conditionally; 00608 00609 std::size_t _M_i; 00610 00611 #ifndef _GLIBCXX_IS_AGGREGATE 00612 throw_value_base() : _M_i(0) 00613 { throw_conditionally(); } 00614 00615 throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i) 00616 { throw_conditionally(); } 00617 00618 #if __cplusplus >= 201103L 00619 // Shall not throw. 00620 throw_value_base(throw_value_base&&) = default; 00621 #endif 00622 00623 explicit throw_value_base(const std::size_t __i) : _M_i(__i) 00624 { throw_conditionally(); } 00625 #endif 00626 00627 throw_value_base& 00628 operator=(const throw_value_base& __v) 00629 { 00630 throw_conditionally(); 00631 _M_i = __v._M_i; 00632 return *this; 00633 } 00634 00635 #if __cplusplus >= 201103L 00636 // Shall not throw. 00637 throw_value_base& 00638 operator=(throw_value_base&&) = default; 00639 #endif 00640 00641 throw_value_base& 00642 operator++() 00643 { 00644 throw_conditionally(); 00645 ++_M_i; 00646 return *this; 00647 } 00648 }; 00649 00650 template<typename _Cond> 00651 inline void 00652 swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b) 00653 { 00654 typedef throw_value_base<_Cond> throw_value; 00655 throw_value::throw_conditionally(); 00656 throw_value orig(__a); 00657 __a = __b; 00658 __b = orig; 00659 } 00660 00661 // General instantiable types requirements. 00662 template<typename _Cond> 00663 inline bool 00664 operator==(const throw_value_base<_Cond>& __a, 00665 const throw_value_base<_Cond>& __b) 00666 { 00667 typedef throw_value_base<_Cond> throw_value; 00668 throw_value::throw_conditionally(); 00669 bool __ret = __a._M_i == __b._M_i; 00670 return __ret; 00671 } 00672 00673 template<typename _Cond> 00674 inline bool 00675 operator<(const throw_value_base<_Cond>& __a, 00676 const throw_value_base<_Cond>& __b) 00677 { 00678 typedef throw_value_base<_Cond> throw_value; 00679 throw_value::throw_conditionally(); 00680 bool __ret = __a._M_i < __b._M_i; 00681 return __ret; 00682 } 00683 00684 // Numeric algorithms instantiable types requirements. 00685 template<typename _Cond> 00686 inline throw_value_base<_Cond> 00687 operator+(const throw_value_base<_Cond>& __a, 00688 const throw_value_base<_Cond>& __b) 00689 { 00690 typedef throw_value_base<_Cond> throw_value; 00691 throw_value::throw_conditionally(); 00692 throw_value __ret(__a._M_i + __b._M_i); 00693 return __ret; 00694 } 00695 00696 template<typename _Cond> 00697 inline throw_value_base<_Cond> 00698 operator-(const throw_value_base<_Cond>& __a, 00699 const throw_value_base<_Cond>& __b) 00700 { 00701 typedef throw_value_base<_Cond> throw_value; 00702 throw_value::throw_conditionally(); 00703 throw_value __ret(__a._M_i - __b._M_i); 00704 return __ret; 00705 } 00706 00707 template<typename _Cond> 00708 inline throw_value_base<_Cond> 00709 operator*(const throw_value_base<_Cond>& __a, 00710 const throw_value_base<_Cond>& __b) 00711 { 00712 typedef throw_value_base<_Cond> throw_value; 00713 throw_value::throw_conditionally(); 00714 throw_value __ret(__a._M_i * __b._M_i); 00715 return __ret; 00716 } 00717 00718 00719 /// Type throwing via limit condition. 00720 struct throw_value_limit : public throw_value_base<limit_condition> 00721 { 00722 typedef throw_value_base<limit_condition> base_type; 00723 00724 #ifndef _GLIBCXX_IS_AGGREGATE 00725 throw_value_limit() { } 00726 00727 throw_value_limit(const throw_value_limit& __other) 00728 : base_type(__other._M_i) { } 00729 00730 #if __cplusplus >= 201103L 00731 throw_value_limit(throw_value_limit&&) = default; 00732 #endif 00733 00734 explicit throw_value_limit(const std::size_t __i) : base_type(__i) { } 00735 #endif 00736 00737 throw_value_limit& 00738 operator=(const throw_value_limit& __other) 00739 { 00740 base_type::operator=(__other); 00741 return *this; 00742 } 00743 00744 #if __cplusplus >= 201103L 00745 throw_value_limit& 00746 operator=(throw_value_limit&&) = default; 00747 #endif 00748 }; 00749 00750 /// Type throwing via random condition. 00751 struct throw_value_random : public throw_value_base<random_condition> 00752 { 00753 typedef throw_value_base<random_condition> base_type; 00754 00755 #ifndef _GLIBCXX_IS_AGGREGATE 00756 throw_value_random() { } 00757 00758 throw_value_random(const throw_value_random& __other) 00759 : base_type(__other._M_i) { } 00760 00761 #if __cplusplus >= 201103L 00762 throw_value_random(throw_value_random&&) = default; 00763 #endif 00764 00765 explicit throw_value_random(const std::size_t __i) : base_type(__i) { } 00766 #endif 00767 00768 throw_value_random& 00769 operator=(const throw_value_random& __other) 00770 { 00771 base_type::operator=(__other); 00772 return *this; 00773 } 00774 00775 #if __cplusplus >= 201103L 00776 throw_value_random& 00777 operator=(throw_value_random&&) = default; 00778 #endif 00779 }; 00780 00781 00782 /** 00783 * @brief Allocator class with logging and exception generation control. 00784 * Intended to be used as an allocator_type in templatized code. 00785 * @ingroup allocators 00786 * 00787 * Note: Deallocate not allowed to throw. 00788 */ 00789 template<typename _Tp, typename _Cond> 00790 class throw_allocator_base 00791 : public annotate_base, public _Cond 00792 { 00793 public: 00794 typedef size_t size_type; 00795 typedef ptrdiff_t difference_type; 00796 typedef _Tp value_type; 00797 typedef value_type* pointer; 00798 typedef const value_type* const_pointer; 00799 typedef value_type& reference; 00800 typedef const value_type& const_reference; 00801 00802 #if __cplusplus >= 201103L 00803 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00804 // 2103. std::allocator propagate_on_container_move_assignment 00805 typedef std::true_type propagate_on_container_move_assignment; 00806 #endif 00807 00808 private: 00809 typedef _Cond condition_type; 00810 00811 std::allocator<value_type> _M_allocator; 00812 00813 using condition_type::throw_conditionally; 00814 00815 public: 00816 size_type 00817 max_size() const _GLIBCXX_USE_NOEXCEPT 00818 { return _M_allocator.max_size(); } 00819 00820 pointer 00821 address(reference __x) const _GLIBCXX_NOEXCEPT 00822 { return std::__addressof(__x); } 00823 00824 const_pointer 00825 address(const_reference __x) const _GLIBCXX_NOEXCEPT 00826 { return std::__addressof(__x); } 00827 00828 pointer 00829 allocate(size_type __n, std::allocator<void>::const_pointer hint = 0) 00830 { 00831 if (__n > this->max_size()) 00832 std::__throw_bad_alloc(); 00833 00834 throw_conditionally(); 00835 pointer const a = _M_allocator.allocate(__n, hint); 00836 insert(a, sizeof(value_type) * __n); 00837 return a; 00838 } 00839 00840 #if __cplusplus >= 201103L 00841 template<typename _Up, typename... _Args> 00842 void 00843 construct(_Up* __p, _Args&&... __args) 00844 { 00845 _M_allocator.construct(__p, std::forward<_Args>(__args)...); 00846 insert_construct(__p); 00847 } 00848 00849 template<typename _Up> 00850 void 00851 destroy(_Up* __p) 00852 { 00853 erase_construct(__p); 00854 _M_allocator.destroy(__p); 00855 } 00856 #else 00857 void 00858 construct(pointer __p, const value_type& val) 00859 { return _M_allocator.construct(__p, val); } 00860 00861 void 00862 destroy(pointer __p) 00863 { _M_allocator.destroy(__p); } 00864 #endif 00865 00866 void 00867 deallocate(pointer __p, size_type __n) 00868 { 00869 erase(__p, sizeof(value_type) * __n); 00870 _M_allocator.deallocate(__p, __n); 00871 } 00872 00873 void 00874 check_allocated(pointer __p, size_type __n) 00875 { 00876 size_type __t = sizeof(value_type) * __n; 00877 annotate_base::check_allocated(__p, __t); 00878 } 00879 00880 void 00881 check(size_type __n) 00882 { annotate_base::check(__n); } 00883 }; 00884 00885 template<typename _Tp, typename _Cond> 00886 inline bool 00887 operator==(const throw_allocator_base<_Tp, _Cond>&, 00888 const throw_allocator_base<_Tp, _Cond>&) 00889 { return true; } 00890 00891 template<typename _Tp, typename _Cond> 00892 inline bool 00893 operator!=(const throw_allocator_base<_Tp, _Cond>&, 00894 const throw_allocator_base<_Tp, _Cond>&) 00895 { return false; } 00896 00897 /// Allocator throwing via limit condition. 00898 template<typename _Tp> 00899 struct throw_allocator_limit 00900 : public throw_allocator_base<_Tp, limit_condition> 00901 { 00902 template<typename _Tp1> 00903 struct rebind 00904 { typedef throw_allocator_limit<_Tp1> other; }; 00905 00906 throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } 00907 00908 throw_allocator_limit(const throw_allocator_limit&) 00909 _GLIBCXX_USE_NOEXCEPT { } 00910 00911 template<typename _Tp1> 00912 throw_allocator_limit(const throw_allocator_limit<_Tp1>&) 00913 _GLIBCXX_USE_NOEXCEPT { } 00914 00915 ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } 00916 }; 00917 00918 /// Allocator throwing via random condition. 00919 template<typename _Tp> 00920 struct throw_allocator_random 00921 : public throw_allocator_base<_Tp, random_condition> 00922 { 00923 template<typename _Tp1> 00924 struct rebind 00925 { typedef throw_allocator_random<_Tp1> other; }; 00926 00927 throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } 00928 00929 throw_allocator_random(const throw_allocator_random&) 00930 _GLIBCXX_USE_NOEXCEPT { } 00931 00932 template<typename _Tp1> 00933 throw_allocator_random(const throw_allocator_random<_Tp1>&) 00934 _GLIBCXX_USE_NOEXCEPT { } 00935 00936 ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } 00937 }; 00938 00939 _GLIBCXX_END_NAMESPACE_VERSION 00940 } // namespace 00941 00942 #if __cplusplus >= 201103L 00943 00944 # include <bits/functional_hash.h> 00945 00946 namespace std _GLIBCXX_VISIBILITY(default) 00947 { 00948 /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit. 00949 template<> 00950 struct hash<__gnu_cxx::throw_value_limit> 00951 : public std::unary_function<__gnu_cxx::throw_value_limit, size_t> 00952 { 00953 size_t 00954 operator()(const __gnu_cxx::throw_value_limit& __val) const 00955 { 00956 __gnu_cxx::throw_value_limit::throw_conditionally(); 00957 std::hash<std::size_t> __h; 00958 size_t __result = __h(__val._M_i); 00959 return __result; 00960 } 00961 }; 00962 00963 /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random. 00964 template<> 00965 struct hash<__gnu_cxx::throw_value_random> 00966 : public std::unary_function<__gnu_cxx::throw_value_random, size_t> 00967 { 00968 size_t 00969 operator()(const __gnu_cxx::throw_value_random& __val) const 00970 { 00971 __gnu_cxx::throw_value_random::throw_conditionally(); 00972 std::hash<std::size_t> __h; 00973 size_t __result = __h(__val._M_i); 00974 return __result; 00975 } 00976 }; 00977 } // end namespace std 00978 #endif 00979 00980 #endif