https://gcc.gnu.org/g:d2970e86c4de89b4ba38fa935f1be65681970c69
commit r15-5217-gd2970e86c4de89b4ba38fa935f1be65681970c69 Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Nov 1 22:20:22 2024 +0000 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 <fdum...@gcc.gnu.org> Diff: --- libstdc++-v3/include/bits/hashtable.h | 99 +++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index f1c30896bcb0..a46a94e2ecd5 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,