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