Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*-
  2.  
  3. // Copyright (C) 2005-2015 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.