This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
hash policy patch
- From: François Dumont <francois dot cppdevs at free dot fr>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 26 Jul 2011 21:49:42 +0200
- Subject: hash policy patch
Hi
Here is an other patch proposal to refactor some code in hash
policy implementation and to fix a potentially exception safety issue in
hashtable. If an exception is raised when hashtable is rehash we need to
restore previous resize value if we still want to guaranty max load factor.
In _M_insert_bucket I have introduced an other try/catch block
around_M_rehash because resize value must be restore only if rehash fail
and not if an exception is raised later. However I don't think any
exception can be thrown later in this method, maybe the deallocation of
the node could be move in the catch clause I have introduce and the
other try/catch block could be removed.
2011-07-26 François Dumont <francois.cppdevs@free.fr>
* include/bits/hashtable_policy.h (_Prime_rehash_policy): Reuse
_M_next_bkt as much as possible.
* include/bits/hashtable.h: Rollback hash policy next resize
value if
rehash generate an exception.
François
Index: include/bits/hashtable.h
===================================================================
--- include/bits/hashtable.h (revision 176806)
+++ include/bits/hashtable.h (working copy)
@@ -913,6 +913,7 @@
_M_insert_bucket(_Arg&& __v, size_type __n,
typename _Hashtable::_Hash_code_type __code)
{
+ const std::size_t __resize = _M_rehash_policy._M_next_resize;
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
@@ -930,7 +931,17 @@
__try
{
if (__do_rehash.first)
- _M_rehash(__do_rehash.second);
+ {
+ __try
+ {
+ _M_rehash(__do_rehash.second);
+ }
+ __catch(...)
+ {
+ _M_rehash_policy._M_next_resize = __resize;
+ __throw_exception_again;
+ }
+ }
__new_node->_M_next = _M_buckets[__n];
this->_M_store_code(__new_node, __code);
@@ -984,11 +995,22 @@
_H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
_M_insert(_Arg&& __v, std::false_type)
{
+ const std::size_t __resize = _M_rehash_policy._M_next_resize;
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, 1);
if (__do_rehash.first)
- _M_rehash(__do_rehash.second);
+ {
+ __try
+ {
+ _M_rehash(__do_rehash.second);
+ }
+ __catch(...)
+ {
+ _M_rehash_policy._M_next_resize = __resize;
+ __throw_exception_again;
+ }
+ }
const key_type& __k = this->_M_extract(__v);
typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
@@ -1027,11 +1049,22 @@
insert(_InputIterator __first, _InputIterator __last)
{
size_type __n_elt = __detail::__distance_fw(__first, __last);
+ const std::size_t __resize = _M_rehash_policy._M_next_resize;
std::pair<bool, std::size_t> __do_rehash
= _M_rehash_policy._M_need_rehash(_M_bucket_count,
_M_element_count, __n_elt);
if (__do_rehash.first)
- _M_rehash(__do_rehash.second);
+ {
+ __try
+ {
+ _M_rehash(__do_rehash.second);
+ }
+ __catch(...)
+ {
+ _M_rehash_policy._M_next_resize = __resize;
+ __throw_exception_again;
+ }
+ }
for (; __first != __last; ++__first)
this->insert(*__first);
Index: include/bits/hashtable_policy.h
===================================================================
--- include/bits/hashtable_policy.h (revision 176806)
+++ include/bits/hashtable_policy.h (working copy)
@@ -441,11 +441,7 @@
_M_bkt_for_elements(std::size_t __n) const
{
const float __min_bkts = __n / _M_max_load_factor;
- const unsigned long __p = *std::lower_bound(__prime_list, __prime_list
- + _S_n_primes, __min_bkts);
- _M_next_resize =
- static_cast<std::size_t>(__builtin_floor(__p * _M_max_load_factor));
- return __p;
+ return _M_next_bkt(__min_bkts);
}
// Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
@@ -469,12 +465,7 @@
if (__min_bkts > __n_bkt)
{
__min_bkts = std::max(__min_bkts, _M_growth_factor * __n_bkt);
- const unsigned long __p =
- *std::lower_bound(__prime_list, __prime_list + _S_n_primes,
- __min_bkts);
- _M_next_resize = static_cast<std::size_t>
- (__builtin_floor(__p * _M_max_load_factor));
- return std::make_pair(true, __p);
+ return std::make_pair(true, _M_next_bkt(__min_bkts));
}
else
{