From 5de90e2673bd0c19de67c68e2fe543444dc1114a Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 18 May 2021 07:41:30 -0700 Subject: [PATCH] Export of internal Abseil changes -- 30af50146f07d7afdb196abf235f44ec44ea6409 by Derek Mauro : Update Abseil dependency versions PiperOrigin-RevId: 374415690 -- 6a241e9ea8ee201789bb66aadf9e1ca9cc23c5dc by Derek Mauro : Fix the install test project, which is doing a mixed-mode build. This manifests in failure with GCC 11, which defaults to C++17 Also explicitly reference python3 in the test script. python2 is being removed by some Linux distros. PiperOrigin-RevId: 374278107 -- 42f85122407e799183880e0b2e2a71f6d35ee003 by Evan Brown : Use `capacity + Group::kWidth` control bytes instead of `capacity + Group::kWidth + 1`. We don't use the extra byte - we only need the first `capacity` ones that are valid, the one sentinel byte and then `Group::kWidth - 1` cloned control bytes. For example, in `EmptyGroup()`, where capacity is 0, we use `Group::kWidth` control bytes. We need to update set_ctrl() to only mirror `Group::kWidth - 1` bytes instead of `Group::kWidth` bytes. Note: this doesn't actually save memory unless `alignof(value_type)` is one. Also add/update related comments. PiperOrigin-RevId: 374198589 -- 5dcd09b2221bf23add583541769b476dac54e112 by Evan Brown : Improve b-tree value_comp() support. - Don't expose internal adapted comparator functionality. - Support value_comp() for maps using function pointer comparators. - For maps, make value_compare's constructor and the member comparator be protected - [reference](https://en.cppreference.com/w/cpp/container/map/value_compare). PiperOrigin-RevId: 373832649 -- d75819786ff5a06e1ed0c5c1e80b3b95ac49c83b by Evan Brown : Don't export adapted comparator functionality in key_comp(). PiperOrigin-RevId: 373651039 GitOrigin-RevId: 30af50146f07d7afdb196abf235f44ec44ea6409 Change-Id: I260480b0923cefeba81c543e2b7c34cacaa7d7c7 --- CMake/install_test_project/CMakeLists.txt | 2 - WORKSPACE | 20 +++++----- absl/container/btree_test.cc | 38 ++++++++++++------ absl/container/internal/btree.h | 47 ++++++++++++++++------- absl/container/internal/btree_container.h | 10 ++--- absl/container/internal/raw_hash_set.h | 14 ++++--- ci/cmake_common.sh | 2 +- create_lts.py | 2 +- 8 files changed, 84 insertions(+), 51 deletions(-) diff --git a/CMake/install_test_project/CMakeLists.txt b/CMake/install_test_project/CMakeLists.txt index 06b797e9..eebfe617 100644 --- a/CMake/install_test_project/CMakeLists.txt +++ b/CMake/install_test_project/CMakeLists.txt @@ -18,8 +18,6 @@ cmake_minimum_required(VERSION 3.5) project(absl_cmake_testing CXX) -set(CMAKE_CXX_STANDARD 11) - add_executable(simple simple.cc) find_package(absl REQUIRED) diff --git a/WORKSPACE b/WORKSPACE index 258d23b5..38db2fde 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -21,25 +21,23 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "com_google_googletest", # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh. - urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"], # 2020-06-12T22:24:28Z - strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b", - sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48", + urls = ["https://github.com/google/googletest/archive/f5e592d8ee5ffb1d9af5be7f715ce3576b8bf9c4.zip"], # 2021-04-29T14:40:44Z + strip_prefix = "googletest-f5e592d8ee5ffb1d9af5be7f715ce3576b8bf9c4", + sha256 = "e61e3889bd5cc3e6bc1084d2108ecda2f110c0387ba88b394ffd16043a1d5709", ) # Google benchmark. http_archive( name = "com_github_google_benchmark", - urls = ["https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip"], # 2020-11-26T11:14:03Z - strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677", - sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c", + urls = ["https://github.com/google/benchmark/archive/7d0d9061d83b663ce05d9de5da3d5865a3845b79.zip"], # 2021-05-11T11:56:00Z + strip_prefix = "benchmark-7d0d9061d83b663ce05d9de5da3d5865a3845b79", + sha256 = "a07789754963e3ea3a1e13fed3a4d48fac0c5f7f749c5065f6c30cd2c1529661", ) # C++ rules for Bazel. http_archive( name = "rules_cc", - sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d", - strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa", - urls = [ - "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip", - ], + urls = ["https://github.com/bazelbuild/rules_cc/archive/ab5395627c80e025e824bd005d41f96b20618b9d.zip"], # 2021-05-10T15:35:04Z + strip_prefix = "rules_cc-ab5395627c80e025e824bd005d41f96b20618b9d", + sha256 = "f3908cb40a6577ab0d1ef9e00052739bf69b4313fa7d20b4d61d4521ea67abf3", ) diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc index 464dabac..d5d79151 100644 --- a/absl/container/btree_test.cc +++ b/absl/container/btree_test.cc @@ -1708,10 +1708,25 @@ TEST(Btree, StrSplitCompatible) { EXPECT_EQ(split_set, expected_set); } -// We can't use EXPECT_EQ/etc. to compare absl::weak_ordering because they -// convert literal 0 to int and absl::weak_ordering can only be compared with -// literal 0. Defining this function allows for avoiding ClangTidy warnings. -bool Identity(const bool b) { return b; } +TEST(Btree, KeyComp) { + absl::btree_set s; + EXPECT_TRUE(s.key_comp()(1, 2)); + EXPECT_FALSE(s.key_comp()(2, 2)); + EXPECT_FALSE(s.key_comp()(2, 1)); + + absl::btree_map m1; + EXPECT_TRUE(m1.key_comp()(1, 2)); + EXPECT_FALSE(m1.key_comp()(2, 2)); + EXPECT_FALSE(m1.key_comp()(2, 1)); + + // Even though we internally adapt the comparator of `m2` to be three-way and + // heterogeneous, the comparator we expose through key_comp() is the original + // unadapted comparator. + absl::btree_map m2; + EXPECT_TRUE(m2.key_comp()("a", "b")); + EXPECT_FALSE(m2.key_comp()("b", "b")); + EXPECT_FALSE(m2.key_comp()("b", "a")); +} TEST(Btree, ValueComp) { absl::btree_set s; @@ -1724,13 +1739,13 @@ TEST(Btree, ValueComp) { EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0))); EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0))); + // Even though we internally adapt the comparator of `m2` to be three-way and + // heterogeneous, the comparator we expose through value_comp() is based on + // the original unadapted comparator. absl::btree_map m2; - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)) < 0)); - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)) == 0)); - EXPECT_TRUE(Identity( - m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)) > 0)); + EXPECT_TRUE(m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0))); + EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0))); + EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0))); } TEST(Btree, DefaultConstruction) { @@ -2906,8 +2921,7 @@ TEST(Btree, SupportsFunctionPtrComparator) { map[1] = 1; EXPECT_THAT(map, ElementsAre(Pair(1, 1))); EXPECT_TRUE(map.key_comp()(1, 2)); - // TODO(ezb): support value_comp() in this case and uncomment. - // EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2))); + EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2))); } template diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index d372a1d6..f636c5fc 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -88,7 +88,12 @@ struct StringBtreeDefaultLess { // Compatibility constructor. StringBtreeDefaultLess(std::less) {} // NOLINT - StringBtreeDefaultLess(std::less) {} // NOLINT + StringBtreeDefaultLess(std::less) {} // NOLINT + + // Allow converting to std::less for use in key_comp()/value_comp(). + explicit operator std::less() const { return {}; } + explicit operator std::less() const { return {}; } + explicit operator std::less() const { return {}; } absl::weak_ordering operator()(absl::string_view lhs, absl::string_view rhs) const { @@ -115,7 +120,12 @@ struct StringBtreeDefaultGreater { StringBtreeDefaultGreater() = default; StringBtreeDefaultGreater(std::greater) {} // NOLINT - StringBtreeDefaultGreater(std::greater) {} // NOLINT + StringBtreeDefaultGreater(std::greater) {} // NOLINT + + // Allow converting to std::greater for use in key_comp()/value_comp(). + explicit operator std::greater() const { return {}; } + explicit operator std::greater() const { return {}; } + explicit operator std::greater() const { return {}; } absl::weak_ordering operator()(absl::string_view lhs, absl::string_view rhs) const { @@ -217,6 +227,8 @@ struct prefers_linear_node_search< template struct common_params { + using original_key_compare = Compare; + // If Compare is a common comparator for a string-like type, then we adapt it // to use heterogeneous lookup and to be a key-compare-to comparator. using key_compare = typename key_compare_to_adapter::type; @@ -317,16 +329,21 @@ struct map_params : common_params + friend class btree; - template - auto operator()(const T &left, const U &right) const - -> decltype(std::declval()(left.first, right.first)) { - return key_compare::operator()(left.first, right.first); + protected: + explicit value_compare(original_key_compare c) : comp(std::move(c)) {} + + original_key_compare comp; // NOLINT + + public: + auto operator()(const value_type &lhs, const value_type &rhs) const + -> decltype(comp(lhs.first, rhs.first)) { + return comp(lhs.first, rhs.first); } }; using is_map_container = std::true_type; @@ -392,7 +409,8 @@ struct set_params : common_params> { using value_type = Key; using slot_type = typename set_params::common_params::slot_type; - using value_compare = typename set_params::common_params::key_compare; + using value_compare = + typename set_params::common_params::original_key_compare; using is_map_container = std::false_type; template @@ -1129,6 +1147,7 @@ class btree { using size_type = typename Params::size_type; using difference_type = typename Params::difference_type; using key_compare = typename Params::key_compare; + using original_key_compare = typename Params::original_key_compare; using value_compare = typename Params::value_compare; using allocator_type = typename Params::allocator_type; using reference = typename Params::reference; @@ -1338,7 +1357,9 @@ class btree { return compare_internal::compare_result_as_less_than(key_comp()(a, b)); } - value_compare value_comp() const { return value_compare(key_comp()); } + value_compare value_comp() const { + return value_compare(original_key_compare(key_comp())); + } // Verifies the structure of the btree. void verify() const; diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h index 03be708e..4f5d56dd 100644 --- a/absl/container/internal/btree_container.h +++ b/absl/container/internal/btree_container.h @@ -51,7 +51,7 @@ class btree_container { using value_type = typename Tree::value_type; using size_type = typename Tree::size_type; using difference_type = typename Tree::difference_type; - using key_compare = typename Tree::key_compare; + using key_compare = typename Tree::original_key_compare; using value_compare = typename Tree::value_compare; using allocator_type = typename Tree::allocator_type; using reference = typename Tree::reference; @@ -214,7 +214,7 @@ class btree_container { allocator_type get_allocator() const { return tree_.get_allocator(); } // The key comparator used by the btree. - key_compare key_comp() const { return tree_.key_comp(); } + key_compare key_comp() const { return key_compare(tree_.key_comp()); } value_compare value_comp() const { return tree_.value_comp(); } // Support absl::Hash. @@ -247,7 +247,7 @@ class btree_set_container : public btree_container { using key_type = typename Tree::key_type; using value_type = typename Tree::value_type; using size_type = typename Tree::size_type; - using key_compare = typename Tree::key_compare; + using key_compare = typename Tree::original_key_compare; using allocator_type = typename Tree::allocator_type; using iterator = typename Tree::iterator; using const_iterator = typename Tree::const_iterator; @@ -398,7 +398,7 @@ class btree_map_container : public btree_set_container { using key_type = typename Tree::key_type; using mapped_type = typename params_type::mapped_type; using value_type = typename Tree::value_type; - using key_compare = typename Tree::key_compare; + using key_compare = typename Tree::original_key_compare; using allocator_type = typename Tree::allocator_type; using iterator = typename Tree::iterator; using const_iterator = typename Tree::const_iterator; @@ -543,7 +543,7 @@ class btree_multiset_container : public btree_container { using key_type = typename Tree::key_type; using value_type = typename Tree::value_type; using size_type = typename Tree::size_type; - using key_compare = typename Tree::key_compare; + using key_compare = typename Tree::original_key_compare; using allocator_type = typename Tree::allocator_type; using iterator = typename Tree::iterator; using const_iterator = typename Tree::const_iterator; diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index b23e0078..669785e6 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -628,7 +628,9 @@ class raw_hash_set { static Layout MakeLayout(size_t capacity) { assert(IsValidCapacity(capacity)); - return Layout(capacity + Group::kWidth + 1, capacity); + // The extra control bytes are for 1 sentinel byte followed by + // `Group::kWidth - 1` bytes that are cloned from the beginning. + return Layout(capacity + Group::kWidth, capacity); } using AllocTraits = absl::allocator_traits; @@ -1782,8 +1784,8 @@ class raw_hash_set { growth_left() = CapacityToGrowth(capacity()) - size_; } - // Sets the control byte, and if `i < Group::kWidth`, set the cloned byte at - // the end too. + // Sets the control byte, and if `i < Group::kWidth - 1`, set the cloned byte + // at the end too. void set_ctrl(size_t i, ctrl_t h) { assert(i < capacity_); @@ -1794,8 +1796,8 @@ class raw_hash_set { } ctrl_[i] = h; - ctrl_[((i - Group::kWidth) & capacity_) + 1 + - ((Group::kWidth - 1) & capacity_)] = h; + constexpr size_t kClonedBytes = Group::kWidth - 1; + ctrl_[((i - kClonedBytes) & capacity_) + (kClonedBytes & capacity_)] = h; } size_t& growth_left() { return settings_.template get<0>(); } @@ -1814,7 +1816,7 @@ class raw_hash_set { // TODO(alkis): Investigate removing some of these fields: // - ctrl/slots can be derived from each other // - size can be moved into the slot array - ctrl_t* ctrl_ = EmptyGroup(); // [(capacity + 1) * ctrl_t] + ctrl_t* ctrl_ = EmptyGroup(); // [(capacity + Group::kWidth) * ctrl_t] slot_type* slots_ = nullptr; // [capacity * slot_type] size_t size_ = 0; // number of full slots size_t capacity_ = 0; // total number of slots diff --git a/ci/cmake_common.sh b/ci/cmake_common.sh index aec8a117..f64dd1a0 100644 --- a/ci/cmake_common.sh +++ b/ci/cmake_common.sh @@ -14,7 +14,7 @@ # The commit of GoogleTest to be used in the CMake tests in this directory. # Keep this in sync with the commit in the WORKSPACE file. -readonly ABSL_GOOGLETEST_COMMIT="8567b09290fe402cf01923e2131c5635b8ed851b" +readonly ABSL_GOOGLETEST_COMMIT="f5e592d8ee5ffb1d9af5be7f715ce3576b8bf9c4" # Avoid depending on GitHub by looking for a cached copy of the commit first. if [[ -r "${KOKORO_GFILE_DIR:-}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then diff --git a/create_lts.py b/create_lts.py index 302812ad..d5d7b28c 100755 --- a/create_lts.py +++ b/create_lts.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # Copyright 2021 The Abseil Authors. #