00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef _THROW_ALLOCATOR_H
00047 #define _THROW_ALLOCATOR_H 1
00048
00049 #include <cmath>
00050 #include <ctime>
00051 #include <map>
00052 #include <string>
00053 #include <ostream>
00054 #include <stdexcept>
00055 #include <utility>
00056 #include <bits/functexcept.h>
00057 #include <bits/move.h>
00058 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00059 # include <functional>
00060 # include <random>
00061 #else
00062 # include <tr1/functional>
00063 # include <tr1/random>
00064 #endif
00065
00066 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
00067
00068
00069
00070
00071
00072 struct forced_error : public std::exception
00073 { };
00074
00075
00076 inline void
00077 __throw_forced_error()
00078 {
00079 #if __EXCEPTIONS
00080 throw forced_error();
00081 #else
00082 __builtin_abort();
00083 #endif
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093 struct annotate_base
00094 {
00095 annotate_base()
00096 {
00097 label();
00098 map();
00099 }
00100
00101 static void
00102 set_label(size_t l)
00103 { label() = l; }
00104
00105 static size_t
00106 get_label()
00107 { return label(); }
00108
00109 void
00110 insert(void* p, size_t size)
00111 {
00112 if (p == NULL)
00113 {
00114 std::string error("annotate_base::insert null insert!\n");
00115 log_to_string(error, make_entry(p, size));
00116 std::__throw_logic_error(error.c_str());
00117 }
00118
00119 const_iterator found = map().find(p);
00120 if (found != map().end())
00121 {
00122 std::string error("annotate_base::insert double insert!\n");
00123 log_to_string(error, make_entry(p, size));
00124 log_to_string(error, *found);
00125 std::__throw_logic_error(error.c_str());
00126 }
00127
00128 map().insert(make_entry(p, size));
00129 }
00130
00131 void
00132 erase(void* p, size_t size)
00133 {
00134 check_allocated(p, size);
00135 map().erase(p);
00136 }
00137
00138
00139 inline void
00140 check_allocated(void* p, size_t size)
00141 {
00142 const_iterator found = map().find(p);
00143 if (found == map().end())
00144 {
00145 std::string error("annotate_base::check_allocated by value "
00146 "null erase!\n");
00147 log_to_string(error, make_entry(p, size));
00148 std::__throw_logic_error(error.c_str());
00149 }
00150
00151 if (found->second.second != size)
00152 {
00153 std::string error("annotate_base::check_allocated by value "
00154 "wrong-size erase!\n");
00155 log_to_string(error, make_entry(p, size));
00156 log_to_string(error, *found);
00157 std::__throw_logic_error(error.c_str());
00158 }
00159 }
00160
00161
00162 inline void
00163 check_allocated(size_t label)
00164 {
00165 const_iterator beg = map().begin();
00166 const_iterator end = map().end();
00167 std::string found;
00168 while (beg != end)
00169 {
00170 if (beg->second.first == label)
00171 log_to_string(found, *beg);
00172 ++beg;
00173 }
00174
00175 if (!found.empty())
00176 {
00177 std::string error("annotate_base::check_allocated by label\n");
00178 error += found;
00179 std::__throw_logic_error(error.c_str());
00180 }
00181 }
00182
00183 private:
00184 typedef std::pair<size_t, size_t> data_type;
00185 typedef std::map<void*, data_type> map_type;
00186 typedef map_type::value_type entry_type;
00187 typedef map_type::const_iterator const_iterator;
00188 typedef map_type::const_reference const_reference;
00189
00190 friend std::ostream&
00191 operator<<(std::ostream&, const annotate_base&);
00192
00193 entry_type
00194 make_entry(void* p, size_t size)
00195 { return std::make_pair(p, data_type(get_label(), size)); }
00196
00197 void
00198 log_to_string(std::string& s, const_reference ref) const
00199 {
00200 char buf[40];
00201 const char tab('\t');
00202 s += "label: ";
00203 unsigned long l = static_cast<unsigned long>(ref.second.first);
00204 __builtin_sprintf(buf, "%lu", l);
00205 s += buf;
00206 s += tab;
00207 s += "size: ";
00208 l = static_cast<unsigned long>(ref.second.second);
00209 __builtin_sprintf(buf, "%lu", l);
00210 s += buf;
00211 s += tab;
00212 s += "address: ";
00213 __builtin_sprintf(buf, "%p", ref.first);
00214 s += buf;
00215 s += '\n';
00216 }
00217
00218 static size_t&
00219 label()
00220 {
00221 static size_t _S_label(std::numeric_limits<size_t>::max());
00222 return _S_label;
00223 }
00224
00225 static map_type&
00226 map()
00227 {
00228 static map_type _S_map;
00229 return _S_map;
00230 }
00231 };
00232
00233 inline std::ostream&
00234 operator<<(std::ostream& os, const annotate_base& __b)
00235 {
00236 std::string error;
00237 typedef annotate_base base_type;
00238 base_type::const_iterator beg = __b.map().begin();
00239 base_type::const_iterator end = __b.map().end();
00240 for (; beg != end; ++beg)
00241 __b.log_to_string(error, *beg);
00242 return os << error;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252 struct condition_base
00253 {
00254 virtual ~condition_base() { };
00255 };
00256
00257
00258
00259
00260
00261 struct limit_condition : public condition_base
00262 {
00263
00264
00265
00266 struct adjustor_base
00267 {
00268 private:
00269 const size_t _M_orig;
00270
00271 public:
00272 adjustor_base() : _M_orig(limit()) { }
00273
00274 virtual
00275 ~adjustor_base() { set_limit(_M_orig); }
00276 };
00277
00278
00279 struct never_adjustor : public adjustor_base
00280 {
00281 never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); }
00282 };
00283
00284
00285 struct always_adjustor : public adjustor_base
00286 {
00287 always_adjustor() { set_limit(count()); }
00288 };
00289
00290
00291 struct limit_adjustor : public adjustor_base
00292 {
00293 limit_adjustor(const size_t __l) { set_limit(__l); }
00294 };
00295
00296
00297
00298 static void
00299 throw_conditionally()
00300 {
00301 if (count() == limit())
00302 __throw_forced_error();
00303 ++count();
00304 }
00305
00306 static size_t&
00307 count()
00308 {
00309 static size_t _S_count(0);
00310 return _S_count;
00311 }
00312
00313 static size_t&
00314 limit()
00315 {
00316 static size_t _S_limit(std::numeric_limits<size_t>::max());
00317 return _S_limit;
00318 }
00319
00320
00321 static void
00322 set_limit(const size_t __l)
00323 {
00324 limit() = __l;
00325 count() = 0;
00326 }
00327 };
00328
00329
00330
00331
00332
00333 struct random_condition : public condition_base
00334 {
00335
00336
00337
00338 struct adjustor_base
00339 {
00340 private:
00341 const double _M_orig;
00342
00343 public:
00344 adjustor_base() : _M_orig(probability()) { }
00345
00346 virtual ~adjustor_base()
00347 { set_probability(_M_orig); }
00348 };
00349
00350
00351 struct group_adjustor : public adjustor_base
00352 {
00353 group_adjustor(size_t size)
00354 { set_probability(1 - std::pow(double(1 - probability()),
00355 double(0.5 / (size + 1))));
00356 }
00357 };
00358
00359
00360 struct never_adjustor : public adjustor_base
00361 {
00362 never_adjustor() { set_probability(0); }
00363 };
00364
00365
00366 struct always_adjustor : public adjustor_base
00367 {
00368 always_adjustor() { set_probability(1); }
00369 };
00370
00371 random_condition()
00372 {
00373 probability();
00374 engine();
00375 }
00376
00377 static void
00378 set_probability(double __p)
00379 { probability() = __p; }
00380
00381 static void
00382 throw_conditionally()
00383 {
00384 if (generate() < probability())
00385 __throw_forced_error();
00386 }
00387
00388 void
00389 seed(unsigned long __s)
00390 { engine().seed(__s); }
00391
00392 private:
00393 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00394 typedef std::uniform_real_distribution<double> distribution_type;
00395 typedef std::mt19937 engine_type;
00396 #else
00397 typedef std::tr1::uniform_real<double> distribution_type;
00398 typedef std::tr1::mt19937 engine_type;
00399 #endif
00400
00401 static double
00402 generate()
00403 {
00404 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00405 const distribution_type distribution(0, 1);
00406 static auto generator = std::bind(distribution, engine());
00407 #else
00408
00409 typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t;
00410 distribution_type distribution(0, 1);
00411 static gen_t generator(engine(), distribution);
00412 #endif
00413
00414 double random = generator();
00415 if (random < distribution.min() || random > distribution.max())
00416 {
00417 std::string __s("random_condition::generate");
00418 __s += "\n";
00419 __s += "random number generated is: ";
00420 char buf[40];
00421 __builtin_sprintf(buf, "%f", random);
00422 __s += buf;
00423 std::__throw_out_of_range(__s.c_str());
00424 }
00425
00426 return random;
00427 }
00428
00429 static double&
00430 probability()
00431 {
00432 static double _S_p;
00433 return _S_p;
00434 }
00435
00436 static engine_type&
00437 engine()
00438 {
00439 static engine_type _S_e;
00440 return _S_e;
00441 }
00442 };
00443
00444
00445
00446
00447
00448
00449
00450
00451 template<typename _Cond>
00452 struct throw_value_base : public _Cond
00453 {
00454 typedef _Cond condition_type;
00455
00456 using condition_type::throw_conditionally;
00457
00458 std::size_t _M_i;
00459
00460 #ifndef _GLIBCXX_IS_AGGREGATE
00461 throw_value_base() : _M_i(0)
00462 { throw_conditionally(); }
00463
00464 throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i)
00465 { throw_conditionally(); }
00466
00467 explicit throw_value_base(const std::size_t __i) : _M_i(__i)
00468 { throw_conditionally(); }
00469 #endif
00470
00471 throw_value_base&
00472 operator=(const throw_value_base& __v)
00473 {
00474 throw_conditionally();
00475 _M_i = __v._M_i;
00476 return *this;
00477 }
00478
00479 throw_value_base&
00480 operator++()
00481 {
00482 throw_conditionally();
00483 ++_M_i;
00484 return *this;
00485 }
00486 };
00487
00488 template<typename _Cond>
00489 inline void
00490 swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b)
00491 {
00492 typedef throw_value_base<_Cond> throw_value;
00493 throw_value::throw_conditionally();
00494 throw_value orig(__a);
00495 __a = __b;
00496 __b = orig;
00497 }
00498
00499
00500 template<typename _Cond>
00501 inline bool
00502 operator==(const throw_value_base<_Cond>& __a,
00503 const throw_value_base<_Cond>& __b)
00504 {
00505 typedef throw_value_base<_Cond> throw_value;
00506 throw_value::throw_conditionally();
00507 bool __ret = __a._M_i == __b._M_i;
00508 return __ret;
00509 }
00510
00511 template<typename _Cond>
00512 inline bool
00513 operator<(const throw_value_base<_Cond>& __a,
00514 const throw_value_base<_Cond>& __b)
00515 {
00516 typedef throw_value_base<_Cond> throw_value;
00517 throw_value::throw_conditionally();
00518 bool __ret = __a._M_i < __b._M_i;
00519 return __ret;
00520 }
00521
00522
00523 template<typename _Cond>
00524 inline throw_value_base<_Cond>
00525 operator+(const throw_value_base<_Cond>& __a,
00526 const throw_value_base<_Cond>& __b)
00527 {
00528 typedef throw_value_base<_Cond> throw_value;
00529 throw_value::throw_conditionally();
00530 throw_value __ret(__a._M_i + __b._M_i);
00531 return __ret;
00532 }
00533
00534 template<typename _Cond>
00535 inline throw_value_base<_Cond>
00536 operator-(const throw_value_base<_Cond>& __a,
00537 const throw_value_base<_Cond>& __b)
00538 {
00539 typedef throw_value_base<_Cond> throw_value;
00540 throw_value::throw_conditionally();
00541 throw_value __ret(__a._M_i - __b._M_i);
00542 return __ret;
00543 }
00544
00545 template<typename _Cond>
00546 inline throw_value_base<_Cond>
00547 operator*(const throw_value_base<_Cond>& __a,
00548 const throw_value_base<_Cond>& __b)
00549 {
00550 typedef throw_value_base<_Cond> throw_value;
00551 throw_value::throw_conditionally();
00552 throw_value __ret(__a._M_i * __b._M_i);
00553 return __ret;
00554 }
00555
00556
00557
00558 struct throw_value_limit : public throw_value_base<limit_condition>
00559 {
00560 typedef throw_value_base<limit_condition> base_type;
00561
00562 #ifndef _GLIBCXX_IS_AGGREGATE
00563 throw_value_limit() { }
00564
00565 throw_value_limit(const throw_value_limit& __other)
00566 : base_type(__other._M_i) { }
00567
00568 explicit throw_value_limit(const std::size_t __i) : base_type(__i) { }
00569 #endif
00570 };
00571
00572
00573 struct throw_value_random : public throw_value_base<random_condition>
00574 {
00575 typedef throw_value_base<random_condition> base_type;
00576
00577 #ifndef _GLIBCXX_IS_AGGREGATE
00578 throw_value_random() { }
00579
00580 throw_value_random(const throw_value_random& __other)
00581 : base_type(__other._M_i) { }
00582
00583
00584 explicit throw_value_random(const std::size_t __i) : base_type(__i) { }
00585 #endif
00586 };
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 template<typename _Tp, typename _Cond>
00597 class throw_allocator_base
00598 : public annotate_base, public _Cond
00599 {
00600 public:
00601 typedef size_t size_type;
00602 typedef ptrdiff_t difference_type;
00603 typedef _Tp value_type;
00604 typedef value_type* pointer;
00605 typedef const value_type* const_pointer;
00606 typedef value_type& reference;
00607 typedef const value_type& const_reference;
00608
00609 private:
00610 typedef _Cond condition_type;
00611
00612 std::allocator<value_type> _M_allocator;
00613
00614 using condition_type::throw_conditionally;
00615
00616 public:
00617 size_type
00618 max_size() const throw()
00619 { return _M_allocator.max_size(); }
00620
00621 pointer
00622 allocate(size_type __n, std::allocator<void>::const_pointer hint = 0)
00623 {
00624 if (__n > this->max_size())
00625 std::__throw_bad_alloc();
00626
00627 throw_conditionally();
00628 pointer const a = _M_allocator.allocate(__n, hint);
00629 insert(a, sizeof(value_type) * __n);
00630 return a;
00631 }
00632
00633 void
00634 construct(pointer __p, const value_type& val)
00635 { return _M_allocator.construct(__p, val); }
00636
00637 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00638 template<typename... _Args>
00639 void
00640 construct(pointer __p, _Args&&... __args)
00641 { return _M_allocator.construct(__p, std::forward<_Args>(__args)...); }
00642 #endif
00643
00644 void
00645 destroy(pointer __p)
00646 { _M_allocator.destroy(__p); }
00647
00648 void
00649 deallocate(pointer __p, size_type __n)
00650 {
00651 erase(__p, sizeof(value_type) * __n);
00652 _M_allocator.deallocate(__p, __n);
00653 }
00654
00655 void
00656 check_allocated(pointer __p, size_type __n)
00657 {
00658 size_type __t = sizeof(value_type) * __n;
00659 annotate_base::check_allocated(__p, __t);
00660 }
00661
00662 void
00663 check_allocated(size_type __n)
00664 { annotate_base::check_allocated(__n); }
00665 };
00666
00667 template<typename _Tp, typename _Cond>
00668 inline bool
00669 operator==(const throw_allocator_base<_Tp, _Cond>&,
00670 const throw_allocator_base<_Tp, _Cond>&)
00671 { return true; }
00672
00673 template<typename _Tp, typename _Cond>
00674 inline bool
00675 operator!=(const throw_allocator_base<_Tp, _Cond>&,
00676 const throw_allocator_base<_Tp, _Cond>&)
00677 { return false; }
00678
00679
00680 template<typename _Tp>
00681 struct throw_allocator_limit
00682 : public throw_allocator_base<_Tp, limit_condition>
00683 {
00684 template<typename _Tp1>
00685 struct rebind
00686 { typedef throw_allocator_limit<_Tp1> other; };
00687
00688 throw_allocator_limit() throw() { }
00689
00690 throw_allocator_limit(const throw_allocator_limit&) throw() { }
00691
00692 template<typename _Tp1>
00693 throw_allocator_limit(const throw_allocator_limit<_Tp1>&) throw() { }
00694
00695 ~throw_allocator_limit() throw() { }
00696 };
00697
00698
00699 template<typename _Tp>
00700 struct throw_allocator_random
00701 : public throw_allocator_base<_Tp, random_condition>
00702 {
00703 template<typename _Tp1>
00704 struct rebind
00705 { typedef throw_allocator_random<_Tp1> other; };
00706
00707 throw_allocator_random() throw() { }
00708
00709 throw_allocator_random(const throw_allocator_random&) throw() { }
00710
00711 template<typename _Tp1>
00712 throw_allocator_random(const throw_allocator_random<_Tp1>&) throw() { }
00713
00714 ~throw_allocator_random() throw() { }
00715 };
00716
00717 _GLIBCXX_END_NAMESPACE
00718
00719 #ifdef __GXX_EXPERIMENTAL_CXX0X__
00720
00721 # include <bits/functional_hash.h>
00722
00723 namespace std
00724 {
00725
00726 template<>
00727 struct hash<__gnu_cxx::throw_value_limit>
00728 : public std::unary_function<__gnu_cxx::throw_value_limit, size_t>
00729 {
00730 size_t
00731 operator()(__gnu_cxx::throw_value_limit __val) const
00732 {
00733 std::hash<std::size_t> h;
00734 size_t __result = h(__val._M_i);
00735 return __result;
00736 }
00737 };
00738
00739
00740 template<>
00741 struct hash<__gnu_cxx::throw_value_random>
00742 : public std::unary_function<__gnu_cxx::throw_value_random, size_t>
00743 {
00744 size_t
00745 operator()(__gnu_cxx::throw_value_random __val) const
00746 {
00747 std::hash<std::size_t> h;
00748 size_t __result = h(__val._M_i);
00749 return __result;
00750 }
00751 };
00752 }
00753 #endif
00754
00755 #endif