From 59e2a562edf0759e0ac52f659d25e0907ed7bec6 Mon Sep 17 00:00:00 2001 From: joaquintides Date: Mon, 2 Jun 2025 12:43:45 +0200 Subject: [PATCH] deprecated `boost::unordered::hash_is_avalanching` in favor of `boost::hash_is_avalanching` (#313) * deprecated boost::unordered::hash_is_avalanching in favor of boost::hash_is_avalanching * replaced deprecation message with simpler BOOST_HEADER_DEPRECATED --- doc/modules/ROOT/pages/changes.adoc | 4 ++ doc/modules/ROOT/pages/hash_quality.adoc | 3 +- doc/modules/ROOT/pages/rationale.adoc | 3 +- .../pages/reference/concurrent_flat_map.adoc | 2 +- .../pages/reference/concurrent_flat_set.adoc | 2 +- .../pages/reference/concurrent_node_map.adoc | 2 +- .../pages/reference/concurrent_node_set.adoc | 2 +- .../ROOT/pages/reference/hash_traits.adoc | 33 +++-------- doc/modules/ROOT/pages/reference/stats.adoc | 3 +- .../pages/reference/unordered_flat_map.adoc | 2 +- .../pages/reference/unordered_flat_set.adoc | 2 +- .../pages/reference/unordered_node_map.adoc | 2 +- .../pages/reference/unordered_node_set.adoc | 2 +- include/boost/unordered/detail/foa/core.hpp | 6 +- include/boost/unordered/hash_traits.hpp | 55 ++----------------- test/unordered/hash_is_avalanching_test.cpp | 6 +- 16 files changed, 36 insertions(+), 93 deletions(-) diff --git a/doc/modules/ROOT/pages/changes.adoc b/doc/modules/ROOT/pages/changes.adoc index 5d0df423..bd801bf4 100644 --- a/doc/modules/ROOT/pages/changes.adoc +++ b/doc/modules/ROOT/pages/changes.adoc @@ -8,6 +8,10 @@ == Release 1.89.0 +* Deprecated `boost::unordered::hash_is_avalanching` is now a using-declaration of +`boost::hash_is_avalanching` in ``. +Use that header directly instead. `` will be +removed in the future. * Added `pull(const_iterator)` to open-addressing containers. This operation allows for efficient removal and retrieval of an element via move construction. diff --git a/doc/modules/ROOT/pages/hash_quality.adoc b/doc/modules/ROOT/pages/hash_quality.adoc index f3a23d26..e6cfd91f 100644 --- a/doc/modules/ROOT/pages/hash_quality.adoc +++ b/doc/modules/ROOT/pages/hash_quality.adoc @@ -43,7 +43,8 @@ struct my_string_hash_function ---- By setting the -`xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]` trait, we inform Boost.Unordered +`link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]` +trait, we inform Boost.Unordered that `my_string_hash_function` is of sufficient quality to be used directly without any post-mixing safety net. This comes at the risk of degraded performance in the cases where the hash function is not as well-behaved as we've declared. diff --git a/doc/modules/ROOT/pages/rationale.adoc b/doc/modules/ROOT/pages/rationale.adoc index 47e483ba..011143a4 100644 --- a/doc/modules/ROOT/pages/rationale.adoc +++ b/doc/modules/ROOT/pages/rationale.adoc @@ -102,7 +102,8 @@ and *high* and *low* are the upper and lower halves of an extended word, respect In 64-bit architectures, _C_ is the integer part of 2^64^∕https://en.wikipedia.org/wiki/Golden_ratio[_φ_], whereas in 32 bits _C_ = 0xE817FB2Du has been obtained from https://arxiv.org/abs/2001.05304[Steele and Vigna (2021)^]. -When using a hash function directly suitable for open addressing, post-mixing can be opted out of via a dedicated `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]` trait. +When using a hash function directly suitable for open addressing, post-mixing can be opted out of via a dedicated +`link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]` trait. `boost::hash` specializations for string types are marked as avalanching. === Platform Interoperability diff --git a/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc b/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc index 42746f06..7e289bdb 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_flat_map.adoc @@ -364,7 +364,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/concurrent_flat_set.adoc b/doc/modules/ROOT/pages/reference/concurrent_flat_set.adoc index 10604868..9d14b0cc 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_flat_set.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_flat_set.adoc @@ -311,7 +311,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc b/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc index 78e63f6e..29a519c9 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_node_map.adoc @@ -381,7 +381,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/concurrent_node_set.adoc b/doc/modules/ROOT/pages/reference/concurrent_node_set.adoc index dd38446d..5826504d 100644 --- a/doc/modules/ROOT/pages/reference/concurrent_node_set.adoc +++ b/doc/modules/ROOT/pages/reference/concurrent_node_set.adoc @@ -328,7 +328,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/hash_traits.adoc b/doc/modules/ROOT/pages/reference/hash_traits.adoc index a311153c..b66e93d2 100644 --- a/doc/modules/ROOT/pages/reference/hash_traits.adoc +++ b/doc/modules/ROOT/pages/reference/hash_traits.adoc @@ -7,39 +7,22 @@ [listing,subs="+macros,+quotes"] ----- +#include + namespace boost { namespace unordered { -template -struct xref:#hash_traits_hash_is_avalanching[hash_is_avalanching]; +using boost::hash_is_avalanching; } // namespace unordered } // namespace boost ----- ---- - -=== hash_is_avalanching -```c++ -template -struct hash_is_avalanching; -``` - -A hash function is said to have the _avalanching property_ if small changes in the input translate to -large changes in the returned hash code —ideally, flipping one bit in the representation of -the input value results in each bit of the hash code flipping with probability 50%. Approaching -this property is critical for the proper behavior of open-addressing hash containers. - -`hash_is_avalanching::value` is: - - * `false` if `Hash::is_avalanching` is not present, - * `Hash::is_avalanching::value` if this is present and convertible at compile time to a `bool`, - * `true` if `Hash::is_avalanching` is `void` (this usage is deprecated), - * ill-formed otherwise. - -Users can then declare a hash function `Hash` as avalanching either by embedding an appropriate `is_avalanching` typedef -into the definition of `Hash`, or directly by specializing `hash_is_avalanching` to a class with -an embedded compile-time constant `value` set to `true`. +[horizontal] +Note:;; This header is deprecated. Use instead +`link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[boost::hash_is_avalanching]` +defined in +`link:../../../../../container_hash/doc/html/hash.html#ref_boostcontainer_hashhash_is_avalanching_hpp[]`. Open-addressing and concurrent containers use the provided hash function `Hash` as-is if `hash_is_avalanching::value` is `true`; otherwise, they diff --git a/doc/modules/ROOT/pages/reference/stats.adoc b/doc/modules/ROOT/pages/reference/stats.adoc index fe690f7a..5d425377 100644 --- a/doc/modules/ROOT/pages/reference/stats.adoc +++ b/doc/modules/ROOT/pages/reference/stats.adoc @@ -66,6 +66,7 @@ If the supplied hash function has good quality, then: * For unsuccessful lookups, the average number of element comparisons should be close to 0.0. These statistics can be used to determine if a given hash function -can be marked as xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[__avalanching__]. +can be marked as +link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[__avalanching__]. --- diff --git a/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc b/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc index 62a1e6f5..4b072f3b 100644 --- a/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_flat_map.adoc @@ -317,7 +317,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/unordered_flat_set.adoc b/doc/modules/ROOT/pages/reference/unordered_flat_set.adoc index 9d1e9892..9a306979 100644 --- a/doc/modules/ROOT/pages/reference/unordered_flat_set.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_flat_set.adoc @@ -266,7 +266,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/unordered_node_map.adoc b/doc/modules/ROOT/pages/reference/unordered_node_map.adoc index 88a05a25..ece3dc43 100644 --- a/doc/modules/ROOT/pages/reference/unordered_node_map.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_node_map.adoc @@ -320,7 +320,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/doc/modules/ROOT/pages/reference/unordered_node_set.adoc b/doc/modules/ROOT/pages/reference/unordered_node_set.adoc index 9af2fc67..bd495efe 100644 --- a/doc/modules/ROOT/pages/reference/unordered_node_set.adoc +++ b/doc/modules/ROOT/pages/reference/unordered_node_set.adoc @@ -270,7 +270,7 @@ The size of the bucket array can be automatically increased by a call to `insert greater than `max_load_factor()`, except possibly for small sizes where the implementation may decide to allow for higher loads. -If `xref:reference/hash_traits.adoc#hash_traits_hash_is_avalanching[hash_is_avalanching]::value` is `true`, the hash function +If `link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[hash_is_avalanching]::value` is `true`, the hash function is used as-is; otherwise, a bit-mixing post-processing stage is added to increase the quality of hashing at the expense of extra computational cost. diff --git a/include/boost/unordered/detail/foa/core.hpp b/include/boost/unordered/detail/foa/core.hpp index 062b7112..ee6cb927 100644 --- a/include/boost/unordered/detail/foa/core.hpp +++ b/include/boost/unordered/detail/foa/core.hpp @@ -1,6 +1,6 @@ /* Common base for Boost.Unordered open-addressing tables. * - * Copyright 2022-2024 Joaquin M Lopez Munoz. + * Copyright 2022-2025 Joaquin M Lopez Munoz. * Copyright 2023 Christian Mazakas. * Copyright 2024 Braden Ganetsky. * Distributed under the Boost Software License, Version 1.0. @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -1426,7 +1426,7 @@ public: using size_policy=pow2_size_policy; using prober=pow2_quadratic_prober; using mix_policy=typename std::conditional< - hash_is_avalanching::value, + boost::hash_is_avalanching::value, no_mix, mulx_mix >::type; diff --git a/include/boost/unordered/hash_traits.hpp b/include/boost/unordered/hash_traits.hpp index 5e2b1af0..41a04a6b 100644 --- a/include/boost/unordered/hash_traits.hpp +++ b/include/boost/unordered/hash_traits.hpp @@ -1,6 +1,6 @@ /* Hash function characterization. * - * Copyright 2022-2024 Joaquin M Lopez Munoz. + * Copyright 2022-2025 Joaquin M Lopez Munoz. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) @@ -11,58 +11,15 @@ #ifndef BOOST_UNORDERED_HASH_TRAITS_HPP #define BOOST_UNORDERED_HASH_TRAITS_HPP -#include +#include +#include + +BOOST_HEADER_DEPRECATED("") namespace boost{ namespace unordered{ -namespace detail{ - -template -struct hash_is_avalanching_impl:std::false_type{}; - -template -struct avalanching_value -{ - static constexpr bool value=IsAvalanching::value; -}; - -/* may be explicitly marked as BOOST_DEPRECATED in the future */ -template<> struct avalanching_value -{ - static constexpr bool value=true; -}; - -template -struct hash_is_avalanching_impl< - Hash, - boost::unordered::detail::void_t ->:std::integral_constant< - bool, - avalanching_value::value ->{}; - -template -struct hash_is_avalanching_impl< - Hash, - typename std::enable_if<((void)Hash::is_avalanching,true)>::type ->{}; /* Hash::is_avalanching is not a type: compile error downstream */ - -} /* namespace detail */ - -/* Each trait can be partially specialized by users for concrete hash functions - * when actual characterization differs from default. - */ - -/* hash_is_avalanching::value is: - * - false if Hash::is_avalanching is not present. - * - Hash::is_avalanching::value if this is present and constexpr-convertible - * to a bool. - * - true if Hash::is_avalanching is void (deprecated). - * - ill-formed otherwise. - */ -template -struct hash_is_avalanching: detail::hash_is_avalanching_impl::type{}; +using boost::hash_is_avalanching; } /* namespace unordered */ } /* namespace boost */ diff --git a/test/unordered/hash_is_avalanching_test.cpp b/test/unordered/hash_is_avalanching_test.cpp index 7ba7e083..8d289d5c 100644 --- a/test/unordered/hash_is_avalanching_test.cpp +++ b/test/unordered/hash_is_avalanching_test.cpp @@ -1,10 +1,9 @@ // Copyright 2022 Peter Dimov -// Copyright 2024 Joaquin M Lopez Munoz +// Copyright 2024-2025 Joaquin M Lopez Munoz // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt // an imitation of a third-party header specializing hash_is_avalanching -// (boost/container_hash/hash.hpp is an example doing that) #include @@ -13,14 +12,11 @@ struct X3 }; namespace boost -{ -namespace unordered { template struct hash_is_avalanching; template<> struct hash_is_avalanching< ::X3 >: boost::true_type {}; -} // namespace unordered } // namespace boost //