[PATCH] _Hashtable fancy pointer support

François Dumont frs.dumont@gmail.com
Thu Jun 26 17:39:40 GMT 2025


No chance to just answer to the question below about how conservative I 
should be ?

Thanks

On 02/06/2025 07:07, François Dumont wrote:
> Hi
>
> It would be nice if someone got some time to review this PR.
>
> Compared to other containers for which support of fancy allocator 
> pointer type have been added the main difference is that in 
> std::_Hashtable usage of the new node types is an abi breaking change, 
> no matter how fancy or not is the allocator's pointer type. This is 
> because in this case hash code is always cached and is put in memory 
> just after pointer to next node. Let me know if I need to be more 
> conservative.
>
>     libstdc++: Add fancy pointer support to std::_Hashtable [PR57272]
>
>     The fancy allocator pointer type support is added to 
> std::unordered_map,
>     std::unordered_multimap, std::unordered_multiset and 
> std::unordered_set
>     through the underlying std::_Hashtable class.
>
>     To respect ABI a new parallel hierarchy of node types has been added.
>     This change introduces new class template parameterized on the 
> allocator's
>     void_pointer type, __hashtable::_Node_base, and new class templates
>     parameterized on the allocator's pointer type, __hashtable::_Node,
>     __hashtable::_Iterator, __hashtable::_Local_iterator. The 
> _Iterator class
>     template is used for both iterator and const_iterator. The 
> _Local_iterator
>     class template is used for both local_iterator and 
> const_local_iterator.
>     Whether std::_Hashtable<K, V, A, KoV, E, H, RH, U, RP, T> should 
> use the old
>     __detail::_Hash_node<V, T::__hash_cached::value> or new
>     __hashtable::_Node<A::pointer> type family internally is 
> controlled by a new
>     __hashtable::_Node_traits traits template. Whether it should use 
> the old
>     __detail::_Node_iterator<V, T::__constant_iterators::value, 
> T::__hash_cached::value>
>     or new __hashtable::_Iterator<Const, 
> T::__constant_iterators::value, A::pointer>
>     type family internally is controlled by 
> __hashtable::_Iterator_traits traits
>     template.
>
>     In case anybody is currently using std::_Hashtable with an 
> allocator that has a
>     fancy pointer, this change will be an ABI break, because their 
> std::_Hashtable
>     instantiations would start to (correctly) use the fancy pointer 
> type. Note that
>     the new type family used in this case is always caching the hash 
> code at node
>     level.
>
>     Because std::_Hashtable will never use fancy pointers in C++98 
> mode, recompiling
>     everything to use fancy pointers isn't even possible if mixing 
> C++98 and C++11
>     code that uses std::_Hashtable. To alleviate this problem, 
> compiling with
>     -D_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE=0 will force 
> std::_Hashtable to have the
>     old, non-conforming behaviour and use raw pointers internally. For 
> testing
>     purposes, compiling with 
> -D_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE=9001 will force
>     std::_Hashtable to always use the new node types.
>
>     This macro is currently undocumented, which needs to be fixed.
>
>     libstdc++-v3/ChangeLog:
>
>             PR libstdc++/57272
>             * include/bits/hashtable.h
>             (__hashtable::_Node_base<>, __hashtable::_Node<>): New.
>             (__hashtable::_Iterator_base<>, __hashtable::_Iterator<>): 
> New.
>             (__hashtable::_Local_iterator<>): New.
>             (__hashtable::_Node_traits<>, 
> __hashtable::_Iterator_traits<>): New.
>             (__hashtable::__alloc_ptr<>): New template alias.
>             (_Hashtable<>::__node_type, __node_alloc_type, 
> __node_alloc_traits, __node_ptr)
>             (__node_base, __node_base_ptr, __buckets_ptr): Rename 
> respectively into...
>             (_Hashtable<>::_Node, _Node_alloc, _Node_alloc_traits, 
> _Node_ptr)
>             (_Node_base, _Base_ptr, _Buckets_ptr): ... those.
>             (_Hashtable<>::_Buckets_ptr_traits): New.
>             (_Hashtable<>::__hash_code_base_access): Remove.
>             (_Hashtable<>::_S_v, _S_next, _M_single_bucket_ptr): New.
>             (_Hashtable<>::_M_node_hash_code, _M_node_hash_code_ext, 
> _M_bucket_index)
>             (_M_bucket_index_ext, _M_key_equals, _M_key_equals_tr, 
> _M_equals, _M_equals_tr)
>             (_M_node_equals): New.
>             (_Hashtable<>::__location_type::_M_base): New.
>             (_Hashtable<>::_S_adapt): New.
>             (_Hashtable<>): Adapt.
>             * include/bits/hashtable_policy.h: Include 
> <bits/ptr_traits.h>.
>             Include <bits/stl_uninitialized.h>.
>             (_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE): New macro, default 
> to 1.
>             (_Hash_node_base::_M_base_ptr): New.
>             (_Hash_node<>::_M_node_ptr): New.
>             (_Hash_code_base<>::_M_hash_code, _M_bucket_index): Remove.
>             (_Hashtable_base<>::_M_key_equals, _M_key_equals_tr): 
> Adapt to only take key
>             type.
>             (_Hashtable_base<>::_M_equals, _M_equals_tr, 
> _M_node_equals): Remove.
>             (_Hashtable_alloc<>): Adapt.
>             * testsuite/23_containers/unordered_map/115939.cc: #undef
>             _GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE as types associated 
> with fancy pointer
>             support do not suffer from the ambiguity issue tested here.
>             * 
> testsuite/23_containers/unordered_map/allocator/ext_ptr.cc: New test.
>             * 
> testsuite/23_containers/unordered_map/requirements/explicit_instantiation/alloc_ptr.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_map/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_multimap/allocator/ext_ptr.cc: New 
> test case.
>             * 
> testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/alloc_ptr.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_multiset/allocator/ext_ptr.cc: New 
> test case.
>             * 
> testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/alloc_ptr.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_set/allocator/ext_ptr.cc: Adapt.
>             * testsuite/23_containers/unordered_set/instantiation_neg.cc:
>             Undef _GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE.
>             * 
> testsuite/23_containers/unordered_set/requirements/explicit_instantiation/alloc_ptr.cc:
>             New test case.
>             * 
> testsuite/23_containers/unordered_set/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>             New test case.
>
> Ok to commit ?
>
> See also:
>
> https://forge.sourceware.org/gcc/gcc-TEST/pulls/32
>
> François
>
>
> On 19/03/2025 21:09, François Dumont wrote:
>> Hi
>>
>> Following latest changes on unordered container I've rebased and 
>> updated this patch to add fancy allocator 's pointer type support in 
>> unordered containers.
>>
>>     libstdc++: Add fancy pointer support to std::_Hashtable [PR57272]
>>
>>     The fancy allocator pointer type support is added to 
>> std::unordered_map,
>>     std::unordered_multimap, std::unordered_multiset and 
>> std::unordered_set
>>     through the underlying std::_Hashtable class.
>>
>>     To respect ABI a new parralel hierarchy of node types has been 
>> added.
>>     This change introduces new class template parameterized on the 
>> allocator's
>>     void_pointer type, __hashtable::_Node_base, and new class templates
>>     parameterized on the allocator's pointer type, __hashtable::_Node,
>>     __hashtable::_Iterator, __hashtable::_Local_iterator. The 
>> _Iterator class
>>     template is used for both iterator and const_iterator. The 
>> _Local_iterator
>>     class template is used for both local_iterator and 
>> const_local_iterator.
>>     Whether std::_Hashtable<K, V, A, KoV, E, H, RH, U, RP, T> should 
>> use the old
>>     __detail::_Hash_node<V, T::__hash_cached::value> or new
>>     __hashtable::_Node<A::pointer> type family internally is 
>> controlled by a new
>>     __hashtable::_Node_traits traits template. Whether it should use 
>> the old
>>     __detail::_Node_iterator<V, T::__constant_iterators::value, 
>> T::__hash_cached::value>
>>     or new __hashtable::_Iterator<Const, 
>> T::__constant_iterators::value, A::pointer>
>>     type family internally is controlled by 
>> __hashtable::_Iterator_traits traits
>>     template.
>>
>>     In case anybody is currently using std::_Hashtable with an 
>> allocator that has a
>>     fancy pointer, this change would be an ABI break, because their 
>> std::_Hashtable
>>     instantiations would start to (correctly) use the fancy pointer 
>> type. If the
>>     fancy pointer just contains a single pointer and so has the same 
>> size, layout,
>>     and object representation as a raw pointer, the code might still 
>> work (despite
>>     being an ODR violation). But if their fancy pointer has a different
>>     representation, they would need to recompile all their code using 
>> that
>>     allocator with std::_Hashtable. Because std::_Hashtable will 
>> never use fancy
>>     pointers in C++98 mode, recompiling everything to use fancy 
>> pointers isn't
>>     even possible if mixing C++98 and C++11 code that uses 
>> std::_Hashtable. To
>>     alleviate this problem, compiling with 
>> -D_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE=0
>>     will force std::_Hashtable to have the old, non-conforming 
>> behaviour and use
>>     raw pointers internally. For testing purposes, compiling with
>>     -D_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE=9001 will force 
>> std::_Hashtable to
>>     always use the new node types. This macro is currently 
>> undocumented, which
>>     needs to be fixed.
>>
>>     Note that the new type family used in case of fancy allocator 
>> pointer type is
>>     always caching the hash code at node level.
>>
>>     libstdc++-v3/ChangeLog:
>>
>>             PR libstdc++/57272
>>             * include/bits/hashtable.h
>>             (__hashtable::_Node_base<>, __hashtable::_Node<>): New.
>>             (__hashtable::_Iterator_base<>, 
>> __hashtable::_Iterator<>): New.
>>             (__hashtable::_Local_iterator<>): New.
>>             (__hashtable::_Node_traits<>, 
>> __hashtable::_Iterator_traits<>): New.
>>             (_Hashtable<>::__node_type, __node_alloc_type, 
>> __node_alloc_traits,
>>             __node_ptr, __node_base, __node_base_ptr, __buckets_ptr): 
>> Rename
>>             respectively into...
>>             (__hashtable::__alloc_ptr<>): New template alias.
>>             (_Hashtable<>::_Node, _Node_alloc, _Node_alloc_traits, 
>> _Node_ptr,
>>             _Node_base, _Base_ptr, _Buckets_ptr): ... those.
>>             (_Hashtable<>::_Buckets_ptr_traits): New.
>>             (_Hashtable<>::__hash_code_base_access): Remove.
>>             (_Hashtable<>::_S_v, _S_next, _M_single_bucket_ptr): New.
>>             (_Hashtable<>::_M_node_hash_code, _M_node_hash_code_ext, 
>> _M_bucket_index,
>>             _M_bucket_index_ext, _M_key_equals, _M_key_equals_tr, 
>> _M_equals, _M_equals_tr,
>>             _M_node_equals): New.
>>             (_Hashtable<>::__location_type::_M_base): New.
>>             (_Hashtable<>::_S_adapt): New.
>>             (_Hashtable<>): Adapt.
>>             * include/bits/hashtable_policy.h: Include 
>> <bits/ptr_traits.h>.
>>             Include <bits/stl_uninitialized.h>.
>>             (_GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE): New macro, 
>> default to 1.
>>             (_Hash_node_base::_M_base_ptr): New.
>>             (_Hash_node<>::_M_node_ptr): New.
>>             (_Hash_code_base<>::_M_hash_code, _M_bucket_index): Remove.
>>             (_Hashtable_base<>::_M_key_equals, _M_key_equals_tr): 
>> Adapt to only take key
>>             type.
>>             (_Hashtable_base<>::_M_equals, _M_equals_tr, 
>> _M_node_equals): Remove.
>>             (_Hashtable_alloc<>): Adapt.
>>             * testsuite/23_containers/unordered_map/115939.cc: #undef
>>             _GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE as types associated 
>> with fancy pointer
>>             support do not suffer from the ambiguity issue tested here.
>>             * 
>> testsuite/23_containers/unordered_map/allocator/ext_ptr.cc: New test.
>>             * 
>> testsuite/23_containers/unordered_map/requirements/explicit_instantiation/alloc_ptr.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_map/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_multimap/allocator/ext_ptr.cc: New 
>> test case.
>>             * 
>> testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/alloc_ptr.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_multimap/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_multiset/allocator/ext_ptr.cc: New 
>> test case.
>>             * 
>> testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/alloc_ptr.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_multiset/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_set/allocator/ext_ptr.cc: Adapt.
>>             * 
>> testsuite/23_containers/unordered_set/instantiation_neg.cc:
>>             Undef _GLIBCXX_USE_ALLOC_PTR_FOR_HASHTABLE.
>>             * 
>> testsuite/23_containers/unordered_set/requirements/explicit_instantiation/alloc_ptr.cc:
>>             New test case.
>>             * 
>> testsuite/23_containers/unordered_set/requirements/explicit_instantiation/alloc_ptr_ignored.cc:
>>             New test case.
>>
>> Available as a PR here:
>>
>> https://forge.sourceware.org/gcc/gcc-TEST/pulls/32
>>
>> François
>>


More information about the Libstdc++ mailing list