libstdc++
throw_allocator.h
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005-2014 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