Commit b0c849fa by François Dumont Committed by Jonathan Wakely

Simplify node ownership in _Hashtable members

Introduce an RAII type to manage nodes in unordered containers while
they are being inserted. If the caller always owns a node until it is
inserted, then the insertion functions don't need to deallocate on
failure. This allows a FIXME in the node re-insertion API to be removed.

Also change extract(const key_type&) to not call extract(const_iterator)
anymore.  This avoids looping through the bucket nodes again to find the
node before the one being extracted.

2019-06-17  François Dumont  <fdumont@gcc.gnu.org>
	    Jonathan Wakely  <jwakely@redhat.com>

	* include/bits/hashtable.h (struct _Hashtable::_Scoped_node): New type.
	(_Hashtable::_M_insert_unique_node): Add key_type parameter. Don't
	deallocate node if insertion fails.
	(_Hashtable::_M_insert_multi_node): Likewise.
	(_Hashtable::_M_reinsert_node): Pass additional key argument.
	(_Hashtable::_M_reinsert_node_multi): Likewise. Remove FIXME.
	(_Hashtable::_M_extract_node(size_t, __node_base*)): New function.
	(_Hashtable::extract(const_iterator)): Use _M_extract_node.
	(_Hashtable::extract(const _Key&)): Likewise.
	(_Hashtable::_M_merge_unique): Pass additional key argument.
	(_Hashtable::_M_emplace<Args>(true_type, Args&&...)): Likewise. Use
	_Scoped_node.
	(_Hashtable::_M_insert): Likewise.
	* include/bits/hashtable_policy.h (_Map_base::operator[]): Likewise.
	(_Hashtable_alloc): Add comments to functions with misleading names.

Co-Authored-By: Jonathan Wakely <jwakely@redhat.com>

From-SVN: r272381
parent e67ddda6
2019-06-17 François Dumont <fdumont@gcc.gnu.org>
Jonathan Wakely <jwakely@redhat.com>
* include/bits/hashtable.h (struct _Hashtable::_Scoped_node): New type.
(_Hashtable::_M_insert_unique_node): Add key_type parameter. Don't
deallocate node if insertion fails.
(_Hashtable::_M_insert_multi_node): Likewise.
(_Hashtable::_M_reinsert_node): Pass additional key argument.
(_Hashtable::_M_reinsert_node_multi): Likewise. Remove FIXME.
(_Hashtable::_M_extract_node(size_t, __node_base*)): New function.
(_Hashtable::extract(const_iterator)): Use _M_extract_node.
(_Hashtable::extract(const _Key&)): Likewise.
(_Hashtable::_M_merge_unique): Pass additional key argument.
(_Hashtable::_M_emplace<Args>(true_type, Args&&...)): Likewise. Use
_Scoped_node.
(_Hashtable::_M_insert): Likewise.
* include/bits/hashtable_policy.h (_Map_base::operator[]): Likewise.
(_Hashtable_alloc): Add comments to functions with misleading names.
2019-06-17 Jonathan Wakely <jwakely@redhat.com>
* testsuite/20_util/bad_function_call/what.cc: Include <string> header
......
......@@ -706,17 +706,19 @@ namespace __detail
__hashtable* __h = static_cast<__hashtable*>(this);
__hash_code __code = __h->_M_hash_code(__k);
std::size_t __bkt = __h->_M_bucket_index(__k, __code);
__node_type* __p = __h->_M_find_node(__bkt, __k, __code);
if (!__p)
{
__p = __h->_M_allocate_node(std::piecewise_construct,
std::tuple<const key_type&>(__k),
std::tuple<>());
return __h->_M_insert_unique_node(__bkt, __code, __p)->second;
}
return __p->_M_v().second;
if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code))
return __node->_M_v().second;
typename __hashtable::_Scoped_node __node {
__h,
std::piecewise_construct,
std::tuple<const key_type&>(__k),
std::tuple<>()
};
auto __pos
= __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node);
__node._M_node = nullptr;
return __pos->second;
}
template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
......@@ -731,17 +733,19 @@ namespace __detail
__hashtable* __h = static_cast<__hashtable*>(this);
__hash_code __code = __h->_M_hash_code(__k);
std::size_t __bkt = __h->_M_bucket_index(__k, __code);
__node_type* __p = __h->_M_find_node(__bkt, __k, __code);
if (!__p)
{
__p = __h->_M_allocate_node(std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::tuple<>());
return __h->_M_insert_unique_node(__bkt, __code, __p)->second;
}
return __p->_M_v().second;
if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code))
return __node->_M_v().second;
typename __hashtable::_Scoped_node __node {
__h,
std::piecewise_construct,
std::forward_as_tuple(std::move(__k)),
std::tuple<>()
};
auto __pos
= __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node);
__node._M_node = nullptr;
return __pos->second;
}
template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
......@@ -1972,8 +1976,8 @@ namespace __detail
}
/**
* This type deals with all allocation and keeps an allocator instance through
* inheritance to benefit from EBO when possible.
* This type deals with all allocation and keeps an allocator instance
* through inheritance to benefit from EBO when possible.
*/
template<typename _NodeAlloc>
struct _Hashtable_alloc : private _Hashtable_ebo_helper<0, _NodeAlloc>
......@@ -2012,17 +2016,21 @@ namespace __detail
_M_node_allocator() const
{ return __ebo_node_alloc::_M_cget(); }
// Allocate a node and construct an element within it.
template<typename... _Args>
__node_type*
_M_allocate_node(_Args&&... __args);
// Destroy the element within a node and deallocate the node.
void
_M_deallocate_node(__node_type* __n);
// Deallocate a node.
void
_M_deallocate_node_ptr(__node_type* __n);
// Deallocate the linked list of nodes pointed to by __n
// Deallocate the linked list of nodes pointed to by __n.
// The elements within the nodes are destroyed.
void
_M_deallocate_nodes(__node_type* __n);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment