diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 910fafcb242f..4e0ddf4c191e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2011-09-17 François Dumont + + * include/bits/hashtable.h (_Hashtable<>::__rehash_policy(const + _RehashPolicy&)): Commit the modification of the policy only if no + exception occured. + * testsuite/23_containers/unordered_set/max_load_factor/robustness.cc: + New. + 2011-09-16 Paolo Carlini * testsuite/23_containers/array/comparison_operators/ diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index b097ee78cb56..5c740668b696 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -741,10 +741,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>:: __rehash_policy(const _RehashPolicy& __pol) { - _M_rehash_policy = __pol; size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count); if (__n_bkt > _M_bucket_count) - _M_rehash(__n_bkt, __pol._M_next_resize); + _M_rehash(__n_bkt, _M_rehash_policy._M_next_resize); + _M_rehash_policy = __pol; } template. + +#include +#include +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef std::numeric_limits nl_size_t; + std::unordered_set, std::equal_to, + __gnu_cxx::throw_allocator_limit > us; + int val = 0; + for (; val != 100; ++val) + { + VERIFY( us.insert(val).second) ; + VERIFY( us.load_factor() <= us.max_load_factor() ); + } + + float cur_max_load_factor = us.max_load_factor(); + int counter = 0; + std::size_t thrown_exceptions = 0; + while (true) + { + __gnu_cxx::limit_condition::set_limit(counter++); + bool do_break = false; + try + { + us.max_load_factor(.5f); + do_break = true; + } + catch (const __gnu_cxx::forced_error&) + { + VERIFY( us.max_load_factor() == cur_max_load_factor ); + ++thrown_exceptions; + } + // Lets check that unordered_set will still be correctly resized + // when needed + __gnu_cxx::limit_condition::set_limit(nl_size_t::max()); + for (;;) + { + VERIFY( us.load_factor() <= us.max_load_factor() ); + size_t nbkts = us.bucket_count(); + VERIFY( us.insert(val++).second ); + if (us.bucket_count() != nbkts) + break; + } + if (do_break) + break; + } + VERIFY( thrown_exceptions > 0 ); +} + +int main() +{ + test01(); + return 0; +}