diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel index 9a723e5..0ec8b92 100644 --- a/absl/algorithm/BUILD.bazel +++ b/absl/algorithm/BUILD.bazel
@@ -83,6 +83,7 @@ "//absl/base:config", "//absl/base:core_headers", "//absl/memory", + "//absl/random", "//absl/types:span", "@googletest//:gtest", "@googletest//:gtest_main",
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt index 252b6b2..f3dd138 100644 --- a/absl/algorithm/CMakeLists.txt +++ b/absl/algorithm/CMakeLists.txt
@@ -68,6 +68,7 @@ absl::config absl::core_headers absl::memory + absl::random_random absl::span GTest::gmock_main )
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index 85e3b11..cb06335 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc
@@ -16,6 +16,7 @@ #include <algorithm> #include <array> +#include <cstddef> #include <functional> #include <initializer_list> #include <iterator> @@ -35,6 +36,7 @@ #include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/memory/memory.h" +#include "absl/random/random.h" #include "absl/types/span.h" namespace { @@ -986,25 +988,16 @@ EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5)); } -template <typename T> -T RandomlySeededPrng() { - std::random_device rdev; - std::seed_seq::result_type data[T::state_size]; - std::generate_n(data, T::state_size, std::ref(rdev)); - std::seed_seq prng_seed(data, data + T::state_size); - return T(prng_seed); -} - TEST(MutatingTest, Shuffle) { std::vector<int> actual = {1, 2, 3, 4, 5}; - absl::c_shuffle(actual, RandomlySeededPrng<std::mt19937_64>()); + absl::c_shuffle(actual, absl::InsecureBitGen()); EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5)); } TEST(MutatingTest, Sample) { std::vector<int> actual; absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3, - RandomlySeededPrng<std::mt19937_64>()); + absl::InsecureBitGen()); EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5})); EXPECT_THAT(actual, SizeIs(3)); }
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 91f930a..61e816f 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel
@@ -494,6 +494,7 @@ "//absl/base:no_destructor", "//absl/memory", "//absl/meta:type_traits", + "//absl/random", "//absl/strings", ], ) @@ -625,6 +626,7 @@ "//absl/base:config", "//absl/base:core_headers", "//absl/profiling:sample_recorder", + "//absl/random", "//absl/synchronization", "//absl/synchronization:thread_pool", "//absl/time", @@ -785,6 +787,7 @@ "//absl/memory", "//absl/meta:type_traits", "//absl/numeric:int128", + "//absl/random", "//absl/strings", "//absl/types:optional", "@googletest//:gtest",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 70f78c4..d8cd7d0 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt
@@ -543,6 +543,7 @@ absl::memory absl::meta absl::no_destructor + absl::random_random absl::strings TESTONLY ) @@ -658,6 +659,7 @@ DEPS absl::config absl::hashtablez_sampler + absl::random_random GTest::gmock_main ) @@ -824,6 +826,7 @@ absl::node_hash_set absl::optional absl::prefetch + absl::random_random absl::raw_hash_set absl::strings absl::test_allocator
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc index e89dfdb..be20e21 100644 --- a/absl/container/internal/hash_generator_testing.cc +++ b/absl/container/internal/hash_generator_testing.cc
@@ -14,61 +14,39 @@ #include "absl/container/internal/hash_generator_testing.h" +#include <algorithm> #include <deque> +#include <random> +#include <string> #include "absl/base/no_destructor.h" +#include "absl/random/random.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { namespace hash_internal { -namespace { - -class RandomDeviceSeedSeq { - public: - using result_type = typename std::random_device::result_type; - - template <class Iterator> - void generate(Iterator start, Iterator end) { - while (start != end) { - *start = gen_(); - ++start; - } - } - - private: - std::random_device gen_; -}; - -} // namespace - -std::mt19937_64* GetSharedRng() { - static absl::NoDestructor<std::mt19937_64> rng([] { - RandomDeviceSeedSeq seed_seq; - return std::mt19937_64(seed_seq); - }()); - return rng.get(); -} std::string Generator<std::string>::operator()() const { + absl::InsecureBitGen gen; // NOLINTNEXTLINE(runtime/int) std::uniform_int_distribution<short> chars(0x20, 0x7E); std::string res; res.resize(32); - std::generate(res.begin(), res.end(), - [&]() { return chars(*GetSharedRng()); }); + std::generate(res.begin(), res.end(), [&]() { return chars(gen); }); return res; } absl::string_view Generator<absl::string_view>::operator()() const { static absl::NoDestructor<std::deque<std::string>> arena; + absl::InsecureBitGen gen; // NOLINTNEXTLINE(runtime/int) std::uniform_int_distribution<short> chars(0x20, 0x7E); arena->emplace_back(); auto& res = arena->back(); res.resize(32); - std::generate(res.begin(), res.end(), - [&]() { return chars(*GetSharedRng()); }); + std::generate(res.begin(), res.end(), [&]() { return chars(gen); }); return res; }
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h index 05be8ef..14c878e 100644 --- a/absl/container/internal/hash_generator_testing.h +++ b/absl/container/internal/hash_generator_testing.h
@@ -23,7 +23,9 @@ #include <algorithm> #include <cassert> #include <iosfwd> +#include <memory> #include <random> +#include <string> #include <tuple> #include <type_traits> #include <utility> @@ -32,6 +34,7 @@ #include "absl/container/internal/hash_policy_testing.h" #include "absl/memory/memory.h" #include "absl/meta/type_traits.h" +#include "absl/random/random.h" #include "absl/strings/string_view.h" namespace absl { @@ -48,8 +51,6 @@ } // namespace generator_internal -std::mt19937_64* GetSharedRng(); - enum Enum : uint64_t { kEnumEmpty, kEnumDeleted, @@ -69,29 +70,27 @@ template <class T> struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> { - T operator()() const { - std::uniform_int_distribution<T> dist; - return dist(*GetSharedRng()); - } + T operator()() const { return dist(gen); } + mutable absl::InsecureBitGen gen; + mutable std::uniform_int_distribution<T> dist; }; template <> struct Generator<Enum> { - Enum operator()() const { - std::uniform_int_distribution<typename std::underlying_type<Enum>::type> - dist; - return static_cast<Enum>(dist(*GetSharedRng())); - } + Enum operator()() const { return static_cast<Enum>(dist(gen)); } + mutable absl::InsecureBitGen gen; + mutable std::uniform_int_distribution< + typename std::underlying_type<Enum>::type> + dist; }; template <> struct Generator<EnumClass> { - EnumClass operator()() const { - std::uniform_int_distribution< - typename std::underlying_type<EnumClass>::type> - dist; - return static_cast<EnumClass>(dist(*GetSharedRng())); - } + EnumClass operator()() const { return static_cast<EnumClass>(dist(gen)); } + mutable absl::InsecureBitGen gen; + mutable std::uniform_int_distribution< + typename std::underlying_type<EnumClass>::type> + dist; }; template <> @@ -135,17 +134,17 @@ template <class U> struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()), - decltype(std::declval<U&>().value())>> + decltype(std::declval<U&>().value())>> : Generator<std::pair< typename std::decay<decltype(std::declval<U&>().key())>::type, typename std::decay<decltype(std::declval<U&>().value())>::type>> {}; template <class Container> -using GeneratedType = decltype( - std::declval<const Generator< - typename std::conditional<generator_internal::IsMap<Container>::value, - typename Container::value_type, - typename Container::key_type>::type>&>()()); +using GeneratedType = + decltype(std::declval<const Generator<typename std::conditional< + generator_internal::IsMap<Container>::value, + typename Container::value_type, + typename Container::key_type>::type>&>()()); // Naive wrapper that performs a linear search of previous values. // Beware this is O(SQR), which is reasonable for smaller kMaxValues.
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc index 24d3bc4..0de1e29 100644 --- a/absl/container/internal/hashtablez_sampler_test.cc +++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -27,6 +27,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/profiling/internal/sample_recorder.h" +#include "absl/random/random.h" #include "absl/synchronization/blocking_counter.h" #include "absl/synchronization/internal/thread_pool.h" #include "absl/synchronization/mutex.h" @@ -439,8 +440,7 @@ const size_t value_size = 13 + i % 5; pool.Schedule([&sampler, &stop, sampling_stride, elt_size, key_size, value_size]() { - std::random_device rd; - std::mt19937 gen(rd()); + absl::InsecureBitGen gen; std::vector<HashtablezInfo*> infoz; while (!stop.HasBeenNotified()) {
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index adba8b1..f66f486 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc
@@ -32,7 +32,6 @@ #include "absl/container/internal/raw_hash_set_resize_impl.h" #include "absl/functional/function_ref.h" #include "absl/hash/hash.h" -#include "absl/numeric/bits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -190,15 +189,8 @@ return capacity < Group::kWidth - 1; } -} // namespace - -FindInfo find_first_non_full(const CommonFields& common, size_t hash) { - return find_first_non_full_from_h1(common.control(), H1(hash, common.seed()), - common.capacity()); -} - -void IterateOverFullSlots(const CommonFields& c, size_t slot_size, - absl::FunctionRef<void(const ctrl_t*, void*)> cb) { +template <class Fn> +void IterateOverFullSlotsImpl(const CommonFields& c, size_t slot_size, Fn cb) { const size_t cap = c.capacity(); const ctrl_t* ctrl = c.control(); void* slot = c.slot_array(); @@ -245,6 +237,8 @@ "hash table was modified unexpectedly"); } +} // namespace + void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) { ABSL_SWISSTABLE_ASSERT(ctrl[capacity] == ctrl_t::kSentinel); ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity)); @@ -256,6 +250,16 @@ ctrl[capacity] = ctrl_t::kSentinel; } +FindInfo find_first_non_full(const CommonFields& common, size_t hash) { + return find_first_non_full_from_h1(common.control(), H1(hash, common.seed()), + common.capacity()); +} + +void IterateOverFullSlots(const CommonFields& c, size_t slot_size, + absl::FunctionRef<void(const ctrl_t*, void*)> cb) { + IterateOverFullSlotsImpl(c, slot_size, cb); +} + namespace { void ResetGrowthLeft(GrowthInfo& growth_info, size_t capacity, size_t size) { @@ -761,6 +765,7 @@ if (has_infoz) { common.set_has_infoz(); common.set_infoz(infoz); + infoz.RecordStorageChanged(common.size(), new_capacity); } } @@ -1630,6 +1635,81 @@ } } +void Copy(CommonFields& common, const PolicyFunctions& policy, + const CommonFields& other, + absl::FunctionRef<void(void*, const void*)> copy_fn) { + const size_t size = other.size(); + ABSL_SWISSTABLE_ASSERT(size > 0); + const size_t soo_capacity = policy.soo_capacity; + const size_t slot_size = policy.slot_size; + if (size <= soo_capacity) { + ABSL_SWISSTABLE_ASSERT(size == 1); + common.set_full_soo(); + const void* other_slot = + other.capacity() <= soo_capacity + ? other.soo_data() + : SlotAddress( + other.slot_array(), + FindFirstFullSlot(0, other.capacity(), other.control()), + slot_size); + copy_fn(common.soo_data(), other_slot); + + if (policy.is_hashtablez_eligible && ShouldSampleNextTable()) { + GrowFullSooTableToNextCapacityForceSampling(common, policy); + } + return; + } + + ReserveTableToFitNewSize(common, policy, size); + auto infoz = common.infoz(); + ABSL_SWISSTABLE_ASSERT(other.capacity() > soo_capacity); + const size_t cap = common.capacity(); + ABSL_SWISSTABLE_ASSERT(cap > soo_capacity); + // Note about single group tables: + // 1. It is correct to have any order of elements. + // 2. Order has to be non deterministic. + // 3. We are assigning elements with arbitrary `shift` starting from + // `capacity + shift` position. + // 4. `shift` must be coprime with `capacity + 1` in order to be able to use + // modular arithmetic to traverse all positions, instead of cycling + // through a subset of positions. Odd numbers are coprime with any + // `capacity + 1` (2^N). + size_t offset = cap; + const size_t shift = is_single_group(cap) ? (common.seed().seed() | 1) : 0; + const void* hash_fn = policy.hash_fn(common); + auto hasher = policy.hash_slot; + IterateOverFullSlotsImpl( + other, slot_size, [&](const ctrl_t* that_ctrl, void* that_slot) { + if (shift == 0) { + // Big tables case. Position must be searched via probing. + // The table is guaranteed to be empty, so we can do faster than + // a full `insert`. + const size_t hash = (*hasher)(hash_fn, that_slot); + FindInfo target = find_first_non_full(common, hash); + infoz.RecordInsert(hash, target.probe_length); + offset = target.offset; + } else { + // Small tables case. Next position is computed via shift. + offset = (offset + shift) & cap; + } + const h2_t h2 = static_cast<h2_t>(*that_ctrl); + // We rely on the hash not changing for small tables. + ABSL_SWISSTABLE_ASSERT( + H2((*hasher)(hash_fn, that_slot)) == h2 && + "hash function value changed unexpectedly during the copy"); + SetCtrl(common, offset, h2, slot_size); + copy_fn(SlotAddress(common.slot_array(), offset, slot_size), that_slot); + common.maybe_increment_generation_on_insert(); + }); + if (shift != 0) { + // On small table copy we do not record individual inserts. + // RecordInsert requires hash, but it is unknown for small tables. + infoz.RecordStorageChanged(size, cap); + } + common.increment_size(size); + common.growth_info().OverwriteManyEmptyAsFull(size); +} + void ReserveTableToFitNewSize(CommonFields& common, const PolicyFunctions& policy, size_t new_size) { common.reset_reserved_growth(new_size);
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index b22f817..f8c0731 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h
@@ -1753,6 +1753,11 @@ // Type erased version of raw_hash_set::rehash. void Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n); +// Type erased version of copy constructor. +void Copy(CommonFields& common, const PolicyFunctions& policy, + const CommonFields& other, + absl::FunctionRef<void(void*, const void*)> copy_fn); + // Returns the optimal size for memcpy when transferring SOO slot. // Otherwise, returns the optimal size for memcpy SOO slot transfer // to SooSlotIndex(). @@ -2166,7 +2171,7 @@ std::is_nothrow_default_constructible<key_equal>::value && std::is_nothrow_default_constructible<allocator_type>::value) {} - ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set( + explicit raw_hash_set( size_t bucket_count, const hasher& hash = hasher(), const key_equal& eq = key_equal(), const allocator_type& alloc = allocator_type()) @@ -2278,73 +2283,17 @@ allocator_type(that.char_alloc_ref()))) {} raw_hash_set(const raw_hash_set& that, const allocator_type& a) - : raw_hash_set(SizeToCapacity(that.size()), that.hash_ref(), - that.eq_ref(), a) { + : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) { that.AssertNotDebugCapacity(); - const size_t size = that.size(); - if (size == 0) { - return; - } - // We don't use `that.is_soo()` here because `that` can have non-SOO - // capacity but have a size that fits into SOO capacity. - if (fits_in_soo(size)) { - ABSL_SWISSTABLE_ASSERT(size == 1); - common().set_full_soo(); - emplace_at(soo_iterator(), *that.begin()); - if (should_sample_soo()) { - GrowFullSooTableToNextCapacityForceSampling(common(), - GetPolicyFunctions()); - } - return; - } - ABSL_SWISSTABLE_ASSERT(!that.is_soo()); - const size_t cap = capacity(); - // Note about single group tables: - // 1. It is correct to have any order of elements. - // 2. Order has to be non deterministic. - // 3. We are assigning elements with arbitrary `shift` starting from - // `capacity + shift` position. - // 4. `shift` must be coprime with `capacity + 1` in order to be able to use - // modular arithmetic to traverse all positions, instead if cycling - // through a subset of positions. Odd numbers are coprime with any - // `capacity + 1` (2^N). - size_t offset = cap; - const size_t shift = - is_single_group(cap) ? (common().seed().seed() | 1) : 0; - IterateOverFullSlots( - that.common(), sizeof(slot_type), - [&](const ctrl_t* that_ctrl, void* that_slot_void) { - slot_type* that_slot = static_cast<slot_type*>(that_slot_void); - if (shift == 0) { - // Big tables case. Position must be searched via probing. - // The table is guaranteed to be empty, so we can do faster than - // a full `insert`. - const size_t hash = PolicyTraits::apply( - HashElement{hash_ref()}, PolicyTraits::element(that_slot)); - FindInfo target = find_first_non_full(common(), hash); - infoz().RecordInsert(hash, target.probe_length); - offset = target.offset; - } else { - // Small tables case. Next position is computed via shift. - offset = (offset + shift) & cap; - } - const h2_t h2 = static_cast<h2_t>(*that_ctrl); - ABSL_SWISSTABLE_ASSERT( // We rely that hash is not changed for small - // tables. - H2(PolicyTraits::apply(HashElement{hash_ref()}, - PolicyTraits::element(that_slot))) == h2 && - "hash function value changed unexpectedly during the copy"); - SetCtrl(common(), offset, h2, sizeof(slot_type)); - emplace_at(iterator_at(offset), PolicyTraits::element(that_slot)); - common().maybe_increment_generation_on_insert(); - }); - if (shift != 0) { - // On small table copy we do not record individual inserts. - // RecordInsert requires hash, but it is unknown for small tables. - infoz().RecordStorageChanged(size, cap); - } - common().increment_size(size); - growth_info().OverwriteManyEmptyAsFull(size); + if (that.empty()) return; + Copy(common(), GetPolicyFunctions(), that.common(), + [this](void* dst, const void* src) { + // TODO(b/413598253): type erase for trivially copyable types via + // PolicyTraits. + construct(to_slot(dst), + PolicyTraits::element( + static_cast<slot_type*>(const_cast<void*>(src)))); + }); } ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept( @@ -2414,7 +2363,7 @@ iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { if (ABSL_PREDICT_FALSE(empty())) return end(); - if (is_soo()) return soo_iterator(); + if (capacity() == 1) return single_iterator(); iterator it = {control(), common().slots_union(), common().generation_ptr()}; it.skip_empty_or_deleted(); @@ -2883,7 +2832,7 @@ // Avoid probing if we won't be able to prefetch the addresses received. #ifdef ABSL_HAVE_PREFETCH prefetch_heap_block(); - auto seq = probe(common(), hash_ref()(key)); + auto seq = probe(common(), hash_of(key)); PrefetchToLocalCache(control() + seq.offset()); PrefetchToLocalCache(slot_array() + seq.offset()); #endif // ABSL_HAVE_PREFETCH @@ -2900,9 +2849,9 @@ template <class K = key_type> iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND { AssertOnFind(key); - if (is_soo()) return find_soo(key); + if (capacity() <= 1) return find_small(key); prefetch_heap_block(); - return find_non_soo(key, hash_ref()(key)); + return find_large(key, hash_of(key)); } template <class K = key_type> @@ -3079,16 +3028,18 @@ // TODO(b/289225379): consider having a helper class that has the impls for // SOO functionality. template <class K = key_type> - iterator find_soo(const key_arg<K>& key) { - ABSL_SWISSTABLE_ASSERT(is_soo()); - return empty() || !PolicyTraits::apply(EqualElement<K>{key, eq_ref()}, - PolicyTraits::element(soo_slot())) + iterator find_small(const key_arg<K>& key) { + ABSL_SWISSTABLE_ASSERT(capacity() <= 1); + return empty() || !PolicyTraits::apply( + EqualElement<K>{key, eq_ref()}, + PolicyTraits::element(single_slot())) ? end() - : soo_iterator(); + : single_iterator(); } template <class K = key_type> - iterator find_non_soo(const key_arg<K>& key, size_t hash) { + iterator find_large(const key_arg<K>& key, size_t hash) { + ABSL_SWISSTABLE_ASSERT(capacity() > 1); ABSL_SWISSTABLE_ASSERT(!is_soo()); auto seq = probe(common(), hash); const h2_t h2 = H2(hash); @@ -3178,6 +3129,10 @@ sizeof(slot_type)); } + template <class K> + size_t hash_of(const K& key) const { + return hash_ref()(key); + } size_t hash_of(slot_type* slot) const { return PolicyTraits::apply(HashElement{hash_ref()}, PolicyTraits::element(slot)); @@ -3310,7 +3265,7 @@ PolicyTraits::transfer_uses_memcpy() && SooEnabled(); size_t index = GrowSooTableToNextCapacityAndPrepareInsert< kUseMemcpy ? OptimalMemcpySizeForSooSlotTransfer(sizeof(slot_type)) : 0, - kUseMemcpy>(common(), GetPolicyFunctions(), hash_ref()(key), + kUseMemcpy>(common(), GetPolicyFunctions(), hash_of(key), soo_slot_ctrl); return {iterator_at(index), true}; } @@ -3319,7 +3274,7 @@ std::pair<iterator, bool> find_or_prepare_insert_non_soo(const K& key) { ABSL_SWISSTABLE_ASSERT(!is_soo()); prefetch_heap_block(); - const size_t hash = hash_ref()(key); + const size_t hash = hash_of(key); auto seq = probe(common(), hash); const h2_t h2 = H2(hash); const ctrl_t* ctrl = control(); @@ -3404,7 +3359,7 @@ } if (empty()) return; - const size_t hash_of_arg = hash_ref()(key); + const size_t hash_of_arg = hash_of(key); const auto assert_consistent = [&](const ctrl_t*, void* slot) { const value_type& element = PolicyTraits::element(static_cast<slot_type*>(slot)); @@ -3452,7 +3407,10 @@ void emplace_at(iterator iter, Args&&... args) { construct(iter.slot(), std::forward<Args>(args)...); - assert(PolicyTraits::apply(FindElement{*this}, *iter) == iter && + // When capacity is 1, find calls find_small and if size is 0, then it will + // return an end iterator. This can happen in the raw_hash_set copy ctor. + assert((capacity() == 1 || + PolicyTraits::apply(FindElement{*this}, *iter) == iter) && "constructed value does not match the lookup key"); } @@ -3528,6 +3486,20 @@ const_iterator soo_iterator() const { return const_cast<raw_hash_set*>(this)->soo_iterator(); } + slot_type* single_slot() { + ABSL_SWISSTABLE_ASSERT(capacity() <= 1); + return SooEnabled() ? soo_slot() : slot_array(); + } + const slot_type* single_slot() const { + return const_cast<raw_hash_set*>(this)->single_slot(); + } + iterator single_iterator() { + return {SooEnabled() ? SooControl() : control(), single_slot(), + common().generation_ptr()}; + } + const_iterator single_iterator() const { + return const_cast<raw_hash_set*>(this)->single_iterator(); + } HashtablezInfoHandle infoz() { ABSL_SWISSTABLE_ASSERT(!is_soo()); return common().infoz(); @@ -3749,7 +3721,7 @@ const typename Set::key_type& key) { if (set.is_soo()) return 0; size_t num_probes = 0; - const size_t hash = set.hash_ref()(key); + const size_t hash = set.hash_of(key); auto seq = probe(set.common(), hash); const h2_t h2 = H2(hash); const ctrl_t* ctrl = set.control();
diff --git a/absl/container/internal/raw_hash_set_benchmark.cc b/absl/container/internal/raw_hash_set_benchmark.cc index b593283..ac94877 100644 --- a/absl/container/internal/raw_hash_set_benchmark.cc +++ b/absl/container/internal/raw_hash_set_benchmark.cc
@@ -172,8 +172,7 @@ // // On a table of size N, keep deleting the LRU entry and add a random one. void BM_CacheInSteadyState(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; string_generator gen{12}; StringTable t; std::deque<std::string> keys; @@ -250,8 +249,7 @@ BENCHMARK(BM_EndComparison); void BM_Iteration(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; string_generator gen{12}; StringTable t; @@ -293,8 +291,7 @@ ->ArgPair(1000, 10); void BM_CopyCtorSparseInt(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; IntTable t; std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{}); @@ -312,8 +309,7 @@ BENCHMARK(BM_CopyCtorSparseInt)->Range(1, 4096); void BM_CopyCtorInt(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; IntTable t; std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{}); @@ -330,8 +326,7 @@ BENCHMARK(BM_CopyCtorInt)->Range(0, 4096); void BM_CopyCtorString(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; StringTable t; std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{}); @@ -348,8 +343,7 @@ BENCHMARK(BM_CopyCtorString)->Range(0, 4096); void BM_CopyAssign(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; IntTable t; std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{}); while (t.size() < state.range(0)) { @@ -365,8 +359,7 @@ BENCHMARK(BM_CopyAssign)->Range(128, 4096); void BM_RangeCtor(benchmark::State& state) { - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{}); std::vector<int> values; const size_t desired_size = state.range(0);
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 2359269..404d1eb 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc
@@ -53,6 +53,7 @@ #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" #include "absl/container/internal/hash_policy_testing.h" +#include "absl/random/random.h" // TODO(b/382423690): Separate tests that depend only on // hashtable_control_bytes. #include "absl/container/internal/hashtable_control_bytes.h" @@ -995,6 +996,21 @@ EXPECT_TRUE(t.empty()); } +TEST(Table, Prefetch) { + IntTable t; + t.emplace(1); + // Works for both present and absent keys. + t.prefetch(1); + t.prefetch(2); + + static constexpr int size = 10; + for (int i = 0; i < size; ++i) t.insert(i); + for (int i = 0; i < size; ++i) { + t.prefetch(i); + ASSERT_TRUE(t.find(i) != t.end()) << i; + } +} + TYPED_TEST(SooTest, LookupEmpty) { TypeParam t; auto it = t.find(0); @@ -1922,8 +1938,7 @@ const std::vector<int64_t>& keys, size_t num_iters) { ProbeStats stats; - std::random_device rd; - std::mt19937 rng(rd()); + absl::InsecureBitGen rng; auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; }; std::uniform_int_distribution<size_t> dist(0, keys.size() - 1); while (num_iters--) { @@ -3012,7 +3027,7 @@ SetSamplingRateTo1Percent(); auto& sampler = GlobalHashtablezSampler(); - size_t start_size = 0; + int64_t start_size = 0; // Reserve the table, so that if it sampled, it'll be preexisting. absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10); start_size += sampler.Iterate([&](const HashtablezInfo& info) { @@ -3025,7 +3040,7 @@ tables.emplace_back(); mutate_table(tables.back()); } - size_t end_size = 0; + int64_t end_size = 0; std::vector<const HashtablezInfo*> infos; end_size += sampler.Iterate([&](const HashtablezInfo& info) { ++end_size; @@ -3107,6 +3122,29 @@ } } +TEST(RawHashSamplerTest, SooTableSampleOnCopy) { + if (SooInt32Table().capacity() != SooCapacity()) { + CHECK_LT(sizeof(void*), 8) << "missing SOO coverage"; + GTEST_SKIP() << "not SOO on this platform"; + } + + SooInt32Table t_orig; + t_orig.insert(1); + + std::vector<const HashtablezInfo*> infos = + SampleSooMutation([&t_orig](SooInt32Table& t) { + t = t_orig; + }); + + for (const HashtablezInfo* info : infos) { + ASSERT_EQ(info->inline_element_size, + sizeof(typename SooInt32Table::value_type)); + ASSERT_EQ(info->soo_capacity, SooCapacity()); + ASSERT_EQ(info->capacity, NextCapacity(SooCapacity())); + ASSERT_EQ(info->size, 1); + } +} + // This tests that rehash(0) on a sampled table with size that fits in SOO // doesn't incorrectly result in losing sampling. TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) { @@ -3141,15 +3179,16 @@ SetSamplingRateTo1Percent(); auto& sampler = GlobalHashtablezSampler(); - size_t start_size = 0; + int64_t start_size = 0; start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; }); std::vector<CustomAllocIntTable> tables; for (int i = 0; i < 100000; ++i) { tables.emplace_back(); tables.back().insert(1); + tables.push_back(tables.back()); // Copies the table. } - size_t end_size = 0; + int64_t end_size = 0; end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; }); EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()), @@ -3660,16 +3699,16 @@ t.insert(1); EXPECT_EQ(HashCount(t), 1); t.erase(1); - EXPECT_EQ(HashCount(t), 2); + EXPECT_LE(HashCount(t), 2); } { Table t; t.insert(3); EXPECT_EQ(HashCount(t), 1); auto node = t.extract(3); - EXPECT_EQ(HashCount(t), 2); + EXPECT_LE(HashCount(t), 2); t.insert(std::move(node)); - EXPECT_EQ(HashCount(t), 3); + EXPECT_LE(HashCount(t), 3); } { Table t;
diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc index d396c58..25073f7 100644 --- a/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -126,6 +126,7 @@ if (pre_signal_frame_pointer >= old_frame_pointer) { new_frame_pointer = pre_signal_frame_pointer; } + } } #endif @@ -137,7 +138,7 @@ // prevent "double fault" in case we hit the first fault due to e.g. // stack corruption. if (!absl::debugging_internal::AddressIsReadable( - new_frame_pointer)) + new_frame_pointer)) { return nullptr; }
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index c1b1f66..c7916b5 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h
@@ -28,13 +28,25 @@ // defined. #include "absl/base/config.h" +// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using +// <version> instead, even though <version> is not available in C++17 mode prior +// to GCC9. +#if defined(__has_include) +#if __has_include(<version>) +#define ABSL_INTERNAL_VERSION_HEADER_AVAILABLE 1 +#endif +#endif + // For feature testing and determining which headers can be included. -#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || \ + ABSL_INTERNAL_VERSION_HEADER_AVAILABLE #include <version> #else #include <ciso646> #endif +#undef ABSL_INTERNAL_VERSION_HEADER_AVAILABLE + #include <algorithm> #include <array> #include <bitset> @@ -84,10 +96,6 @@ #include <string_view> #endif -#ifdef __ARM_ACLE -#include <arm_acle.h> -#endif - namespace absl { ABSL_NAMESPACE_BEGIN @@ -1081,8 +1089,7 @@ }; static constexpr uint64_t kMul = - sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51} - : uint64_t{0xdcb22ca68cb134ed}; + uint64_t{0xdcb22ca68cb134ed}; template <typename T> using IntegralFastPath = @@ -1140,10 +1147,9 @@ MixingHashState hash_state, WeaklyMixedInteger value) { // Some transformation for the value is needed to make an empty // string/container change the mixing hash state. - // Seed() is most likely already in a register. - // TODO(b/384509507): experiment with using kMul or last 31 bits of kMul. - // See https://godbolt.org/z/6cM77s3PW for ideas. - return MixingHashState{hash_state.state_ + (Seed() + value.value)}; + // We use constant smaller than 8 bits to make compiler use + // `add` with an immediate operand with 1 byte value. + return MixingHashState{hash_state.state_ + (0x57 + value.value)}; } template <typename CombinerT>
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel index c052105..44ec71b 100644 --- a/absl/log/internal/BUILD.bazel +++ b/absl/log/internal/BUILD.bazel
@@ -425,10 +425,6 @@ hdrs = ["proto.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - visibility = [ - ":internal_users", - ":structured_proto_users", - ], deps = [ "//absl/base", "//absl/base:config",
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel index 3c7a02f..f455d1e 100644 --- a/absl/numeric/BUILD.bazel +++ b/absl/numeric/BUILD.bazel
@@ -124,6 +124,7 @@ deps = [ ":int128", "//absl/base:config", + "//absl/random", "@google_benchmark//:benchmark_main", ], )
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc index e2e2de5..c37abec 100644 --- a/absl/numeric/int128_benchmark.cc +++ b/absl/numeric/int128_benchmark.cc
@@ -13,31 +13,29 @@ // limitations under the License. #include <algorithm> +#include <cstddef> #include <cstdint> #include <limits> #include <random> +#include <type_traits> +#include <utility> #include <vector> #include "absl/base/config.h" #include "absl/numeric/int128.h" +#include "absl/random/random.h" #include "benchmark/benchmark.h" namespace { constexpr size_t kSampleSize = 1000000; -std::mt19937 MakeRandomEngine() { - std::random_device r; - std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); - return std::mt19937(seed); -} - template <typename T, typename H = typename std::conditional< std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type> std::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() { std::vector<std::pair<T, T>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; std::uniform_int_distribution<H> uniform_h; values.reserve(kSampleSize); for (size_t i = 0; i < kSampleSize; ++i) { @@ -77,7 +75,7 @@ std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type> std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() { std::vector<std::pair<T, H>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; std::uniform_int_distribution<H> uniform_h; values.reserve(kSampleSize); for (size_t i = 0; i < kSampleSize; ++i) { @@ -114,7 +112,7 @@ std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() { std::vector<std::pair<absl::uint128, absl::uint128>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; std::uniform_int_distribution<uint64_t> uniform_uint64; values.reserve(kSampleSize); for (size_t i = 0; i < kSampleSize; ++i) { @@ -155,7 +153,8 @@ class UniformIntDistribution128 { public: // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API - T operator()(std::mt19937& generator) { + template <class URBG> + T operator()(URBG& generator) { return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator); } @@ -168,7 +167,7 @@ std::is_same<T, __int128>::value, int64_t, uint64_t>::type> std::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() { std::vector<std::pair<T, T>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; UniformIntDistribution128<T> uniform_128; values.reserve(kSampleSize); for (size_t i = 0; i < kSampleSize; ++i) { @@ -209,7 +208,7 @@ std::is_same<T, __int128>::value, int64_t, uint64_t>::type> std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() { std::vector<std::pair<T, H>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; UniformIntDistribution128<T> uniform_int128; std::uniform_int_distribution<H> uniform_int64; values.reserve(kSampleSize); @@ -246,9 +245,9 @@ BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128); std::vector<std::pair<unsigned __int128, unsigned __int128>> - GetRandomIntrinsic128Sample() { +GetRandomIntrinsic128Sample() { std::vector<std::pair<unsigned __int128, unsigned __int128>> values; - std::mt19937 random = MakeRandomEngine(); + absl::InsecureBitGen random; UniformIntDistribution128<unsigned __int128> uniform_uint128; values.reserve(kSampleSize); for (size_t i = 0; i < kSampleSize; ++i) {
diff --git a/absl/profiling/BUILD.bazel b/absl/profiling/BUILD.bazel index c5e3b00..ee4800d 100644 --- a/absl/profiling/BUILD.bazel +++ b/absl/profiling/BUILD.bazel
@@ -56,6 +56,7 @@ deps = [ ":sample_recorder", "//absl/base:core_headers", + "//absl/random", "//absl/synchronization", "//absl/synchronization:thread_pool", "//absl/time",
diff --git a/absl/profiling/CMakeLists.txt b/absl/profiling/CMakeLists.txt index 9b3a710..84b8b3b 100644 --- a/absl/profiling/CMakeLists.txt +++ b/absl/profiling/CMakeLists.txt
@@ -32,6 +32,7 @@ COPTS ${ABSL_TEST_COPTS} DEPS + absl::random_random absl::sample_recorder absl::time GTest::gmock_main
diff --git a/absl/profiling/internal/sample_recorder_test.cc b/absl/profiling/internal/sample_recorder_test.cc index 3373329..a037f9d 100644 --- a/absl/profiling/internal/sample_recorder_test.cc +++ b/absl/profiling/internal/sample_recorder_test.cc
@@ -15,14 +15,20 @@ #include "absl/profiling/internal/sample_recorder.h" #include <atomic> +#include <cassert> +#include <cstddef> +#include <cstdint> #include <random> #include <vector> #include "gmock/gmock.h" +#include "gtest/gtest.h" #include "absl/base/thread_annotations.h" +#include "absl/random/random.h" #include "absl/synchronization/internal/thread_pool.h" #include "absl/synchronization/mutex.h" #include "absl/synchronization/notification.h" +#include "absl/time/clock.h" #include "absl/time/time.h" namespace absl { @@ -112,9 +118,7 @@ for (int i = 0; i < 10; ++i) { pool.Schedule([&sampler, &stop, i]() { - std::random_device rd; - std::mt19937 gen(rd()); - + absl::InsecureBitGen gen; std::vector<Info*> infoz; while (!stop.HasBeenNotified()) { if (infoz.empty()) {
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 3b0aab5..49562f7 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel
@@ -250,6 +250,7 @@ visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/random", "@google_benchmark//:benchmark_main", ], ) @@ -360,6 +361,7 @@ ":strings", "//absl/base:core_headers", "//absl/base:raw_logging_internal", + "//absl/random", "@google_benchmark//:benchmark_main", ], ) @@ -1358,6 +1360,7 @@ ":str_format", ":str_format_internal", ":strings", + "//absl/random", "@googletest//:gtest", "@googletest//:gtest_main", ],
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index ec731d8..ee73860 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt
@@ -545,6 +545,7 @@ COPTS ${ABSL_TEST_COPTS} DEPS + absl::random_random absl::str_format absl::str_format_internal absl::strings
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc index a839019..435090d 100644 --- a/absl/strings/ascii_benchmark.cc +++ b/absl/strings/ascii_benchmark.cc
@@ -16,9 +16,9 @@ #include <array> #include <cctype> #include <cstddef> -#include <random> #include <string> +#include "absl/random/random.h" #include "absl/strings/ascii.h" #include "benchmark/benchmark.h" @@ -27,10 +27,8 @@ std::array<unsigned char, 256> MakeShuffledBytes() { std::array<unsigned char, 256> bytes; for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i); - std::random_device rd; - std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); - std::mt19937 g(seed); - std::shuffle(bytes.begin(), bytes.end(), g); + absl::InsecureBitGen gen; + std::shuffle(bytes.begin(), bytes.end(), gen); return bytes; }
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc index 694c126..fc4dc4f 100644 --- a/absl/strings/internal/str_format/extension_test.cc +++ b/absl/strings/internal/str_format/extension_test.cc
@@ -16,11 +16,13 @@ #include "absl/strings/internal/str_format/extension.h" +#include <cstddef> #include <random> #include <string> #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/random/random.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" @@ -44,8 +46,7 @@ namespace { std::string MakeRandomString(size_t len) { - std::random_device rd; - std::mt19937 gen(rd()); + absl::InsecureBitGen gen; std::uniform_int_distribution<> dis('a', 'z'); std::string s(len, '0'); for (char& c : s) {
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 3d9a173..1a82087 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc
@@ -41,7 +41,6 @@ #include "gtest/gtest.h" #include "absl/log/log.h" #include "absl/numeric/int128.h" -#include "absl/random/distributions.h" #include "absl/random/random.h" #include "absl/strings/internal/numbers_test_common.h" #include "absl/strings/internal/ostringstream.h" @@ -1368,13 +1367,10 @@ const size_t kNumRandomTests = 10000; -template <typename IntType> -void test_random_integer_parse_base(bool (*parse_func)(absl::string_view, - IntType* value, - int base)) { - using RandomEngine = std::minstd_rand0; - std::random_device rd; - RandomEngine rng(rd()); +template <typename IntType, + bool parse_func(absl::string_view, IntType* value, int base)> +void test_random_integer_parse_base() { + absl::InsecureBitGen rng; std::uniform_int_distribution<IntType> random_int( std::numeric_limits<IntType>::min()); std::uniform_int_distribution<int> random_base(2, 36); @@ -1406,34 +1402,32 @@ } TEST(stringtest, safe_strto16_random) { - test_random_integer_parse_base<int16_t>(&safe_strto16_base); + test_random_integer_parse_base<int16_t, safe_strto16_base>(); } TEST(stringtest, safe_strto32_random) { - test_random_integer_parse_base<int32_t>(&safe_strto32_base); + test_random_integer_parse_base<int32_t, safe_strto32_base>(); } TEST(stringtest, safe_strto64_random) { - test_random_integer_parse_base<int64_t>(&safe_strto64_base); + test_random_integer_parse_base<int64_t, safe_strto64_base>(); } TEST(stringtest, safe_strtou16_random) { - test_random_integer_parse_base<uint16_t>(&safe_strtou16_base); + test_random_integer_parse_base<uint16_t, safe_strtou16_base>(); } TEST(stringtest, safe_strtou32_random) { - test_random_integer_parse_base<uint32_t>(&safe_strtou32_base); + test_random_integer_parse_base<uint32_t, safe_strtou32_base>(); } TEST(stringtest, safe_strtou64_random) { - test_random_integer_parse_base<uint64_t>(&safe_strtou64_base); + test_random_integer_parse_base<uint64_t, safe_strtou64_base>(); } TEST(stringtest, safe_strtou128_random) { // random number generators don't work for uint128 so this code must be custom // implemented for uint128, but is generally the same as what's above. // test_random_integer_parse_base<absl::uint128>( // &absl::numbers_internal::safe_strtou128_base); - using RandomEngine = std::minstd_rand0; using IntType = absl::uint128; constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base; - std::random_device rd; - RandomEngine rng(rd()); + absl::InsecureBitGen rng; std::uniform_int_distribution<uint64_t> random_uint64( std::numeric_limits<uint64_t>::min()); std::uniform_int_distribution<int> random_base(2, 36); @@ -1464,12 +1458,10 @@ // implemented for int128, but is generally the same as what's above. // test_random_integer_parse_base<absl::int128>( // &absl::numbers_internal::safe_strto128_base); - using RandomEngine = std::minstd_rand0; using IntType = absl::int128; constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base; - std::random_device rd; - RandomEngine rng(rd()); + absl::InsecureBitGen rng; std::uniform_int_distribution<int64_t> random_int64( std::numeric_limits<int64_t>::min()); std::uniform_int_distribution<uint64_t> random_uint64(
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc index 4e36687..546f6ed 100644 --- a/absl/strings/string_view_benchmark.cc +++ b/absl/strings/string_view_benchmark.cc
@@ -24,6 +24,7 @@ #include "absl/base/attributes.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/macros.h" +#include "absl/random/random.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "benchmark/benchmark.h" @@ -286,9 +287,7 @@ "found", "a", "large", "mushroom", "and", "a", "couple", "crickets", "eating", "pie"}; // Create some keys that consist of words in random order. - std::random_device r; - std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); - std::mt19937 rng(seed); + absl::InsecureBitGen rng; std::vector<std::string> keys(table_size); std::vector<int> all_indices; const int kBlockSize = 1 << 12;
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index c3c271e..920928e 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel
@@ -266,6 +266,7 @@ "//absl/log", "//absl/log:check", "//absl/memory", + "//absl/random", "//absl/time", "@googletest//:gtest", "@googletest//:gtest_main",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 4d21067..9d4844d 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt
@@ -193,6 +193,7 @@ absl::core_headers absl::log absl::memory + absl::random_random absl::time GTest::gmock_main )
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index d8c4fdf..a3eb3db 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc
@@ -36,6 +36,7 @@ #include "absl/log/check.h" #include "absl/log/log.h" #include "absl/memory/memory.h" +#include "absl/random/random.h" #include "absl/synchronization/internal/create_thread_identity.h" #include "absl/synchronization/internal/thread_pool.h" #include "absl/time/clock.h" @@ -1064,8 +1065,7 @@ static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv, int *running) { - std::random_device dev; - std::mt19937 gen(dev()); + absl::InsecureBitGen gen; std::uniform_int_distribution<int> random_millis(0, 15); mu->ReaderLock(); while (*running == 3) {
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel index 445bdcc..ad0313c 100644 --- a/absl/time/BUILD.bazel +++ b/absl/time/BUILD.bazel
@@ -99,6 +99,7 @@ "//absl/base:core_headers", "//absl/hash:hash_testing", "//absl/numeric:int128", + "//absl/random", "//absl/strings:str_format", "//absl/time/internal/cctz:time_zone", "@googletest//:gtest",
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt index a48689c..ea91ba3 100644 --- a/absl/time/CMakeLists.txt +++ b/absl/time/CMakeLists.txt
@@ -49,7 +49,7 @@ "internal/cctz/include/cctz/civil_time.h" "internal/cctz/include/cctz/civil_time_detail.h" SRCS - "internal/cctz/src/civil_time_detail.cc" + "internal/cctz/src/civil_time_detail.cc" COPTS ${ABSL_DEFAULT_COPTS} ) @@ -122,6 +122,7 @@ absl::config absl::core_headers absl::hash_testing + absl::random_random absl::strings absl::str_format absl::time_zone
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index 573a76a..1e3fe67 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc
@@ -40,6 +40,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/random/random.h" #include "absl/strings/str_format.h" #include "absl/time/time.h" @@ -1514,9 +1515,7 @@ } TEST(Duration, ToDoubleSecondsCheckRandom) { - std::random_device rd; - std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()}); - std::mt19937_64 gen(seed); + absl::InsecureBitGen gen; // We want doubles distributed from 1/8ns up to 2^63, where // as many values are tested from 1ns to 2ns as from 1sec to 2sec, // so even distribute along a log-scale of those values, and