aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-11-01 22:20:22 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2024-11-13 20:21:40 +0000
commitd2970e86c4de89b4ba38fa935f1be65681970c69 (patch)
tree216001b8e2640deb29ded8e25fc4a1f51ca66d32
parente717c322c6ee21bd5d9cf9373dcd9b4e8ba3312f (diff)
downloadgcc-d2970e86c4de89b4ba38fa935f1be65681970c69.zip
gcc-d2970e86c4de89b4ba38fa935f1be65681970c69.tar.gz
gcc-d2970e86c4de89b4ba38fa935f1be65681970c69.tar.bz2
libstdc++: Use RAII in _Hashtable
Use scoped guard types to clean up if an exception is thrown. This allows some try-catch blocks to be removed. libstdc++-v3/ChangeLog: * include/bits/hashtable.h (operator=(const _Hashtable&)): Use RAII instead of try-catch. (_M_assign(_Ht&&, _NodeGenerator&)): Likewise. Reviewed-by: François Dumont <fdumont@gcc.gnu.org>
-rw-r--r--libstdc++-v3/include/bits/hashtable.h99
1 files changed, 55 insertions, 44 deletions
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index f1c3089..a46a94e 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -1307,17 +1307,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_bucket_count = __ht._M_bucket_count;
_M_element_count = __ht._M_element_count;
_M_rehash_policy = __ht._M_rehash_policy;
- __try
- {
- _M_assign(__ht);
- }
- __catch(...)
- {
- // _M_assign took care of deallocating all memory. Now we
- // must make sure this instance remains in a usable state.
- _M_reset();
- __throw_exception_again;
- }
+
+ struct _Guard
+ {
+ ~_Guard() { if (_M_ht) _M_ht->_M_reset(); }
+ _Hashtable* _M_ht;
+ };
+ // If _M_assign exits via an exception it will have deallocated
+ // all memory. This guard will ensure *this is in a usable state.
+ _Guard __guard{this};
+ _M_assign(__ht);
+ __guard._M_ht = nullptr;
return *this;
}
std::__alloc_on_copy(__this_alloc, __that_alloc);
@@ -1390,46 +1390,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
_M_assign(_Ht&& __ht, _NodeGenerator& __node_gen)
{
- __buckets_ptr __buckets = nullptr;
- if (!_M_buckets)
- _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
+ struct _Guard
+ {
+ ~_Guard()
+ {
+ if (_M_ht)
+ {
+ _M_ht->clear();
+ if (_M_dealloc_buckets)
+ _M_ht->_M_deallocate_buckets();
+ }
+ }
+ _Hashtable* _M_ht = nullptr;
+ bool _M_dealloc_buckets = false;
+ };
+ _Guard __guard;
- __try
+ if (!_M_buckets)
{
- if (!__ht._M_before_begin._M_nxt)
- return;
+ _M_buckets = _M_allocate_buckets(_M_bucket_count);
+ __guard._M_dealloc_buckets = true;
+ }
- using _FromVal = __conditional_t<is_lvalue_reference<_Ht>::value,
- const value_type&, value_type&&>;
+ if (!__ht._M_before_begin._M_nxt)
+ return;
- // First deal with the special first node pointed to by
- // _M_before_begin.
- __node_ptr __ht_n = __ht._M_begin();
- __node_ptr __this_n
- = __node_gen(static_cast<_FromVal>(__ht_n->_M_v()));
- this->_M_copy_code(*__this_n, *__ht_n);
- _M_update_bbegin(__this_n);
+ __guard._M_ht = this;
- // Then deal with other nodes.
- __node_ptr __prev_n = __this_n;
- for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
- {
- __this_n = __node_gen(static_cast<_FromVal>(__ht_n->_M_v()));
- __prev_n->_M_nxt = __this_n;
- this->_M_copy_code(*__this_n, *__ht_n);
- size_type __bkt = _M_bucket_index(*__this_n);
- if (!_M_buckets[__bkt])
- _M_buckets[__bkt] = __prev_n;
- __prev_n = __this_n;
- }
- }
- __catch(...)
+ using _FromVal = __conditional_t<is_lvalue_reference<_Ht>::value,
+ const value_type&, value_type&&>;
+
+ // First deal with the special first node pointed to by
+ // _M_before_begin.
+ __node_ptr __ht_n = __ht._M_begin();
+ __node_ptr __this_n
+ = __node_gen(static_cast<_FromVal>(__ht_n->_M_v()));
+ this->_M_copy_code(*__this_n, *__ht_n);
+ _M_update_bbegin(__this_n);
+
+ // Then deal with other nodes.
+ __node_ptr __prev_n = __this_n;
+ for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
{
- clear();
- if (__buckets)
- _M_deallocate_buckets();
- __throw_exception_again;
+ __this_n = __node_gen(static_cast<_FromVal>(__ht_n->_M_v()));
+ __prev_n->_M_nxt = __this_n;
+ this->_M_copy_code(*__this_n, *__ht_n);
+ size_type __bkt = _M_bucket_index(*__this_n);
+ if (!_M_buckets[__bkt])
+ _M_buckets[__bkt] = __prev_n;
+ __prev_n = __this_n;
}
+ __guard._M_ht = nullptr;
}
template<typename _Key, typename _Value, typename _Alloc,