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