[PATCH] Hashtable PR96088

François Dumont frs.dumont@gmail.com
Thu May 6 20:03:18 GMT 2021


Hi

     Considering your feedback on backtrace in debug mode is going to 
take me some time so here is another one.

     Compared to latest submission I've added a _Hash_arg_t partial 
specialization for std::hash<>. It is not strictly necessary for the 
moment but when we will eventually remove its nested argument_type it 
will be. I also wonder if it is not easier to handle for the compiler, 
not sure about that thought.

Tested under Linux x86_64, ok to commit ?

François


On 04/12/20 10:10 am, François Dumont wrote:
> Following submission of the heterogeneous lookup in unordered 
> containers I rebased this patch on top of it.
>
> Appart from reducing its size because of some code reuse the 
> heterogeneous lookup had no impact on this one. This is because when I 
> cannot find out if conversion from inserted element type to hash 
> functor can throw then I pass the element as-is, like if hash functor 
> was transparent.
>
>     libstdc++: Limit allocation on iterator insertion in Hashtable [PR 
> 96088]
>
>     Detect Hash functor argument type to find out if it is different 
> to the
>     container key_type and if a temporary instance needs to be 
> generated to invoke
>     the functor from the iterator value_type key part. If this 
> temporary generation
>     can throw a key_type instance is generated at Hashtable level and 
> used to call
>     the functors and, if necessary, moved to the storage.
>
>     libstdc++-v3/ChangeLog:
>
>             PR libstdc++/96088
>             * include/bits/hashtable_policy.h (_Select2nd): New.
>             (_NodeBuilder<>): New.
>             (_ReuseOrAllocNode<>::operator()): Use variadic template 
> args.
>             (_AllocNode<>::operator()): Likewise.
>             (_Hash_code_base<>::_M_hash_code): Add _Kt template 
> parameter.
>             (_Hashtable_base<>::_M_equals): Add _Kt template parameter.
>             * include/bits/hashtable.h
>             (_Hashtable<>::__node_builder_t): New.
>             (_Hashtable<>::_M_find_before_node): Add _Kt template 
> parameter.
>             (_Hashtable<>::_M_find_node): Likewise.
>             (_Hashtable<>::_Hash_arg_t): New.
>             (_Hashtable<>::_S_forward_key): New.
> (_Hashtable<>::_M_insert_unique<>(_Kt&&, _Arg&&, const _NodeGenerator&)):
>              New.
>             (_Hashtable<>::_M_insert): Use latter.
>             * testsuite/23_containers/unordered_map/96088.cc: New test.
>             * testsuite/23_containers/unordered_multimap/96088.cc: New 
> test.
>             * testsuite/23_containers/unordered_multiset/96088.cc: New 
> test.
>             * testsuite/23_containers/unordered_set/96088.cc: New test.
>             * testsuite/util/replacement_memory_operators.h
>             (counter::_M_increment): New.
>             (counter::_M_decrement): New.
>             (counter::reset()): New.
>
> Note that I plan to change counter type name to something more 
> meaningful but only when back to stage 1.
>
> François
>
> On 24/10/20 4:25 pm, François Dumont wrote:
>> Hi
>>
>>     Just a rebase of this patch.
>>
>> François
>>
>> On 17/10/20 6:21 pm, François Dumont wrote:
>>> I eventually would like to propose the following resolution.
>>>
>>> For multi-key containers I kept the same resolution build the node 
>>> first and compute has code from the node key.
>>>
>>> For unique-key ones I change behavior when I can't find out hash 
>>> functor argument type. I am rather using the iterator key type and 
>>> just hope that the user's functors are prepared for it.
>>>
>>> For now I am using functor argument_type which is deprecated. I just 
>>> hope that the day we remove it we will have a compiler built-in to 
>>> get any functor argument type given an input type.
>>>
>>>     libstdc++: Limit allocation on iterator insertion in Hashtable 
>>> [PR 96088]
>>>
>>>     Detect Hash functor argument type to find out if it is different 
>>> to the
>>>     container key_type and if a temporary instance needs to be 
>>> generated to invoke
>>>     the functor from the iterator value_type key part. If this 
>>> temporary generation
>>>     can throw a key_type instance is generated at Hashtable level 
>>> and use to call
>>>     the functors and, if needed, move it to the storage.
>>>
>>>     libstdc++-v3/ChangeLog:
>>>
>>>             PR libstdc++/96088
>>>             * include/bits/hashtable_policy.h (_Select2nd): New.
>>>             (_NodeBuilder<>): New.
>>>             (_ReuseOrAllocNode<>::operator()): Use varriadic 
>>> template args.
>>>             (_AllocNode<>::operator()): Likewise.
>>>             (_Hash_code_base<>::_M_hash_code): Add _KType template 
>>> parameter.
>>>             (_Hashtable_base<>::_M_equals): Add _KType template 
>>> parameter.
>>>             * include/bits/hashtable.h
>>>             (_Hashtable<>::__node_builder_t): New.
>>>             (_Hashtable<>::_M_find_before_node): Add _KType template 
>>> parameter.
>>>             (_Hashtable<>::_M_find_node): Likewise.
>>>             (_Hashtable<>::_Hash_arg_t): New.
>>>             (_Hashtable<>::_S_forward_key): New.
>>> (_Hashtable<>::_M_insert_unique<>(_KType&&, _Arg&&, const 
>>> _NodeGenerator&)):
>>>              New.
>>>             (_Hashtable<>::_M_insert): Use latter.
>>>             * testsuite/23_containers/unordered_map/96088.cc: New test.
>>>             * testsuite/23_containers/unordered_multimap/96088.cc: 
>>> New test.
>>>             * testsuite/23_containers/unordered_multiset/96088.cc: 
>>> New test.
>>>             * testsuite/23_containers/unordered_set/96088.cc: New test.
>>>             * testsuite/util/replacement_memory_operators.h
>>>             (counter::_M_increment): New.
>>>             (counter::_M_decrement): New.
>>>             (counter::reset()): New.
>>>
>>> Tested under Linux x86_64.
>>>
>>> Ok to commit ?
>>>
>>> François
>>>
>>> On 01/09/20 2:36 pm, François Dumont wrote:
>>>> Hi
>>>>
>>>>     I started working on PR96088 problem in Hashtable implementation.
>>>>
>>>>     In the case of multi-key containers the problem is easy to 
>>>> manage. Now that we have _Scoped_node we can easily allocate the 
>>>> node first and then extract the key from it to compute hash code. 
>>>> It is quite safe as computating a hash code is rarely going to 
>>>> throw especially if there is no allocation anymore to invoke the 
>>>> hasher.
>>>>
>>>>     In the unique-key case it is more tricky. First I only consider 
>>>> the hasher invocation, the equal_to shall be consistent with it. My 
>>>> approach is to consider that if the operation needed transform the 
>>>> inserted element key part into the hasher argument can throw then I 
>>>> better generate a key_type instance myself and move it to the node 
>>>> if it is eventually to be inserted. Note that any allocation needed 
>>>> to call the hasher from the key_type is user fault.
>>>>
>>>>     Of course the tricky part here is to find out what is the 
>>>> hasher argument_type. For the moment I support hasher with a nested 
>>>> argument_type typedef and function pointer. But, as pointed out by 
>>>> the tests which are failing for the moment I am missing the support 
>>>> for a classic functor. I am pretty sure that if I support it I will 
>>>> still be missing some use cases (like std::function). So I am 
>>>> looking for help on how to determine it. Or maybe the whole 
>>>> approach it wrong ?
>>>>
>>>> For now I am still working on it, thanks,
>>>>
>>>> François
>>>>
>>>
>>
>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: hashtable.patch
Type: text/x-patch
Size: 25892 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20210506/c91021cc/attachment-0001.bin>


More information about the Libstdc++ mailing list