This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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
 	  {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]