libstdc++
throw_allocator.h
Go to the documentation of this file.
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