diff options
Diffstat (limited to 'absl/container')
-rw-r--r-- | absl/container/BUILD.bazel | 3 | ||||
-rw-r--r-- | absl/container/CMakeLists.txt | 3 | ||||
-rw-r--r-- | absl/container/internal/common_policy_traits.h | 15 | ||||
-rw-r--r-- | absl/container/internal/common_policy_traits_test.cc | 9 | ||||
-rw-r--r-- | absl/container/internal/container_memory.h | 13 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set_test.cc | 27 |
6 files changed, 57 insertions, 13 deletions
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 71afe9d2..15162f28 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -637,6 +637,8 @@ cc_test( ], deps = [ ":container_memory", + ":flat_hash_map", + ":flat_hash_set", ":hash_function_defaults", ":hash_policy_testing", ":hashtable_debug", @@ -646,6 +648,7 @@ cc_test( "//absl/base:core_headers", "//absl/base:prefetch", "//absl/base:raw_logging_internal", + "//absl/log", "//absl/strings", "@com_google_googletest//:gtest_main", ], diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index a3fdb969..6c2931b6 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -722,12 +722,15 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::container_memory + absl::flat_hash_map + absl::flat_hash_set absl::hash_function_defaults absl::hash_policy_testing absl::hashtable_debug absl::raw_hash_set absl::base absl::config + absl::log absl::core_headers absl::prefetch absl::raw_logging_internal diff --git a/absl/container/internal/common_policy_traits.h b/absl/container/internal/common_policy_traits.h index cc2e89ba..c99e68f4 100644 --- a/absl/container/internal/common_policy_traits.h +++ b/absl/container/internal/common_policy_traits.h @@ -16,6 +16,7 @@ #define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_ #include <cstddef> +#include <cstring> #include <memory> #include <new> #include <type_traits> @@ -32,7 +33,8 @@ template <class Policy, class = void> struct common_policy_traits { // The actual object stored in the container. using slot_type = typename Policy::slot_type; - + using reference = decltype(Policy::element(std::declval<slot_type*>())); + using value_type = typename std::remove_reference<reference>::type; // PRECONDITION: `slot` is UNINITIALIZED // POSTCONDITION: `slot` is INITIALIZED @@ -89,6 +91,17 @@ struct common_policy_traits { template <class Alloc> static void transfer_impl(Alloc* alloc, slot_type* new_slot, slot_type* old_slot, char) { +#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 + if (absl::is_trivially_relocatable<value_type>()) { + // TODO(b/247130232): remove cast after fixing class-memaccess warning. + std::memcpy(static_cast<void*>( + std::launder(const_cast<std::remove_const_t<value_type>*>( + &element(new_slot)))), + &element(old_slot), sizeof(value_type)); + return; + } +#endif + construct(alloc, new_slot, std::move(element(old_slot))); destroy(alloc, old_slot); } diff --git a/absl/container/internal/common_policy_traits_test.cc b/absl/container/internal/common_policy_traits_test.cc index 768d870e..5eaa4aae 100644 --- a/absl/container/internal/common_policy_traits_test.cc +++ b/absl/container/internal/common_policy_traits_test.cc @@ -27,7 +27,7 @@ namespace container_internal { namespace { using ::testing::MockFunction; -using ::testing::Return; +using ::testing::AnyNumber; using ::testing::ReturnRef; using Slot = int; @@ -101,9 +101,10 @@ TEST_F(Test, element) { TEST_F(Test, without_transfer) { int b = 42; - EXPECT_CALL(element, Call(&b)).WillOnce(::testing::ReturnRef(b)); - EXPECT_CALL(construct, Call(&alloc, &a, b)); - EXPECT_CALL(destroy, Call(&alloc, &b)); + EXPECT_CALL(element, Call(&a)).Times(AnyNumber()).WillOnce(ReturnRef(a)); + EXPECT_CALL(element, Call(&b)).WillOnce(ReturnRef(b)); + EXPECT_CALL(construct, Call(&alloc, &a, b)).Times(AnyNumber()); + EXPECT_CALL(destroy, Call(&alloc, &b)).Times(AnyNumber()); common_policy_traits<PolicyWithoutOptionalOps>::transfer(&alloc, &a, &b); } diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index 00e9f6d7..c29c533b 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -17,6 +17,7 @@ #include <cassert> #include <cstddef> +#include <cstring> #include <memory> #include <new> #include <tuple> @@ -340,7 +341,8 @@ template <class K, class V> struct map_slot_policy { using slot_type = map_slot_type<K, V>; using value_type = std::pair<const K, V>; - using mutable_value_type = std::pair<K, V>; + using mutable_value_type = + std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>; private: static void emplace(slot_type* slot) { @@ -424,6 +426,15 @@ struct map_slot_policy { static void transfer(Allocator* alloc, slot_type* new_slot, slot_type* old_slot) { emplace(new_slot); +#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 + if (absl::is_trivially_relocatable<value_type>()) { + // TODO(b/247130232): remove cast after fixing class-memaccess warning. + std::memcpy(static_cast<void*>(std::launder(&new_slot->value)), + &old_slot->value, sizeof(value_type)); + return; + } +#endif + if (kMutableKeys::value) { absl::allocator_traits<Allocator>::construct( *alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value)); diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index f77ffbc1..eec9da43 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -14,17 +14,25 @@ #include "absl/container/internal/raw_hash_set.h" +#include <algorithm> #include <atomic> #include <cmath> #include <cstdint> #include <deque> #include <functional> +#include <iterator> +#include <list> +#include <map> #include <memory> #include <numeric> +#include <ostream> #include <random> #include <string> +#include <type_traits> #include <unordered_map> #include <unordered_set> +#include <utility> +#include <vector> #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -33,10 +41,13 @@ #include "absl/base/internal/cycleclock.h" #include "absl/base/internal/prefetch.h" #include "absl/base/internal/raw_logging.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" #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/container/internal/hashtable_debug.h" +#include "absl/log/log.h" #include "absl/strings/string_view.h" namespace absl { @@ -339,7 +350,7 @@ class StringPolicy { struct ctor {}; template <class... Ts> - slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {} + explicit slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {} std::pair<std::string, std::string> pair; }; @@ -411,7 +422,7 @@ struct CustomAlloc : std::allocator<T> { CustomAlloc() {} template <typename U> - CustomAlloc(const CustomAlloc<U>& other) {} + explicit CustomAlloc(const CustomAlloc<U>& /*other*/) {} template<class U> struct rebind { using other = CustomAlloc<U>; @@ -1275,6 +1286,7 @@ TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) { for (size_t size : sizes) { auto& stat = stats[size]; VerifyStats(size, expected, stat); + LOG(INFO) << size << " " << stat; } } @@ -1370,6 +1382,7 @@ TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) { for (size_t size : sizes) { auto& stat = stats[size]; VerifyStats(size, expected, stat); + LOG(INFO) << size << " " << stat; } } @@ -1504,7 +1517,7 @@ TEST(Table, RehashZeroForcesRehash) { TEST(Table, ConstructFromInitList) { using P = std::pair<std::string, std::string>; struct Q { - operator P() const { return {}; } + operator P() const { return {}; } // NOLINT }; StringTable t = {P(), Q(), {}, {{}, {}}}; } @@ -2027,7 +2040,7 @@ TEST(Table, UnstablePointers) { TEST(TableDeathTest, EraseOfEndAsserts) { // Use an assert with side-effects to figure out if they are actually enabled. bool assert_enabled = false; - assert([&]() { + assert([&]() { // NOLINT assert_enabled = true; return true; }()); @@ -2047,7 +2060,7 @@ TEST(RawHashSamplerTest, Sample) { auto& sampler = GlobalHashtablezSampler(); size_t start_size = 0; - std::unordered_set<const HashtablezInfo*> preexisting_info; + absl::flat_hash_set<const HashtablezInfo*> preexisting_info; start_size += sampler.Iterate([&](const HashtablezInfo& info) { preexisting_info.insert(&info); ++start_size; @@ -2074,8 +2087,8 @@ TEST(RawHashSamplerTest, Sample) { } } size_t end_size = 0; - std::unordered_map<size_t, int> observed_checksums; - std::unordered_map<ssize_t, int> reservations; + absl::flat_hash_map<size_t, int> observed_checksums; + absl::flat_hash_map<ssize_t, int> reservations; end_size += sampler.Iterate([&](const HashtablezInfo& info) { if (preexisting_info.count(&info) == 0) { observed_checksums[info.hashes_bitwise_xor.load( |