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