throw_allocator.h 24 KB

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