Commit 1e3d25b2 by Abseil Team Committed by Gennadiy Rozental

Export of internal Abseil changes

--
017c3924d21132085bc20c9be0ae469bfbf2c56c by Gennadiy Rozental <rogeeff@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 338723934

--
8b08c23d7b05232e283b1388cee3eb5bebc2d9c4 by Derek Mauro <dmauro@google.com>:

Add script to test GCC floor (the minimum version of GCC we support,
currently the GCC 5 series)

PiperOrigin-RevId: 338708581

--
afa440ac7c843126b4f99b89ebc071dda1d85a4d by Abseil Team <absl-team@google.com>:

Fix typo in documentation of StatusOr::value_or() ('of' -> 'if').

PiperOrigin-RevId: 338690089

--
97d5008865327fc36b942b96de0d0cacfb909df5 by Derek Mauro <dmauro@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 338568224

--
da5e09a7fedb3217329465d9206b7cbc6677176b by Abseil Team <absl-team@google.com>:

Add `absl_btree_prefer_linear_node_search`

Allow keys of `btree_set`, `btree_map`, `btree_multiset`, and `btree_multimap`
to opt-in to linear search (instead of binary search).  Linear search was
used previously for arithmetic types with `key_compare` of `std::greater`
or `std::less`.

For example, this would be useful for key types that wrap an integer
and define their own cheap `operator<()`.

```
 class K {
  public:
   using absl_btree_prefer_linear_node_search = std::true_type;
   ...
  private:
   friend bool operator<(K a, K b) { return a.k_ < b.k_; }
   int k_;
 };

 absl::btree_map<K, V> m;  // Uses linear search
 assert((absl::btree_map<K, V>::testonly_uses_linear_node_search()));
```

PiperOrigin-RevId: 338476553

--
c56ead7ce6b0a5ad32e3a42904c686448a69451e by Gennadiy Rozental <rogeeff@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 338419417
GitOrigin-RevId: 017c3924d21132085bc20c9be0ae469bfbf2c56c
Change-Id: I1199f3ae917280a3ef20ccc6038abbe34d96ec0b
parent eb317a70
...@@ -1216,6 +1216,70 @@ class BtreeNodePeer { ...@@ -1216,6 +1216,70 @@ class BtreeNodePeer {
namespace { namespace {
class BtreeMapTest : public ::testing::Test {
public:
struct Key {};
struct Cmp {
template <typename T>
bool operator()(T, T) const {
return false;
}
};
struct KeyLin {
using absl_btree_prefer_linear_node_search = std::true_type;
};
struct CmpLin : Cmp {
using absl_btree_prefer_linear_node_search = std::true_type;
};
struct KeyBin {
using absl_btree_prefer_linear_node_search = std::false_type;
};
struct CmpBin : Cmp {
using absl_btree_prefer_linear_node_search = std::false_type;
};
template <typename K, typename C>
static bool IsLinear() {
return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
}
};
TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
// Test requesting linear search by directly exporting an alias.
EXPECT_FALSE((IsLinear<Key, Cmp>()));
EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
EXPECT_TRUE((IsLinear<Key, CmpLin>()));
EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
}
TEST_F(BtreeMapTest, LinearChoiceTree) {
// Cmp has precedence, and is forcing binary
EXPECT_FALSE((IsLinear<Key, CmpBin>()));
EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
EXPECT_FALSE((IsLinear<int, CmpBin>()));
EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
// Cmp has precedence, and is forcing linear
EXPECT_TRUE((IsLinear<Key, CmpLin>()));
EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
EXPECT_TRUE((IsLinear<int, CmpLin>()));
EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
// Cmp has no preference, Key determines linear vs binary.
EXPECT_FALSE((IsLinear<Key, Cmp>()));
EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
// arithmetic key w/ std::less or std::greater: linear
EXPECT_TRUE((IsLinear<int, std::less<int>>()));
EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
// arithmetic key w/ custom compare: binary
EXPECT_FALSE((IsLinear<int, Cmp>()));
// non-arithmetic key: binary
EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
}
TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) { TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
absl::btree_map<std::string, std::unique_ptr<std::string>> m; absl::btree_map<std::string, std::unique_ptr<std::string>> m;
......
...@@ -182,6 +182,38 @@ struct key_compare_to_adapter<std::greater<absl::Cord>> { ...@@ -182,6 +182,38 @@ struct key_compare_to_adapter<std::greater<absl::Cord>> {
using type = StringBtreeDefaultGreater; using type = StringBtreeDefaultGreater;
}; };
// Detects an 'absl_btree_prefer_linear_node_search' member. This is
// a protocol used as an opt-in or opt-out of linear search.
//
// For example, this would be useful for key types that wrap an integer
// and define their own cheap operator<(). For example:
//
// class K {
// public:
// using absl_btree_prefer_linear_node_search = std::true_type;
// ...
// private:
// friend bool operator<(K a, K b) { return a.k_ < b.k_; }
// int k_;
// };
//
// btree_map<K, V> m; // Uses linear search
//
// If T has the preference tag, then it has a preference.
// Btree will use the tag's truth value.
template <typename T, typename = void>
struct has_linear_node_search_preference : std::false_type {};
template <typename T, typename = void>
struct prefers_linear_node_search : std::false_type {};
template <typename T>
struct has_linear_node_search_preference<
T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
: std::true_type {};
template <typename T>
struct prefers_linear_node_search<
T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
: T::absl_btree_prefer_linear_node_search {};
template <typename Key, typename Compare, typename Alloc, int TargetNodeSize, template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
bool Multi, typename SlotPolicy> bool Multi, typename SlotPolicy>
struct common_params { struct common_params {
...@@ -424,15 +456,22 @@ class btree_node { ...@@ -424,15 +456,22 @@ class btree_node {
using difference_type = typename Params::difference_type; using difference_type = typename Params::difference_type;
// Btree decides whether to use linear node search as follows: // Btree decides whether to use linear node search as follows:
// - If the comparator expresses a preference, use that.
// - If the key expresses a preference, use that.
// - If the key is arithmetic and the comparator is std::less or // - If the key is arithmetic and the comparator is std::less or
// std::greater, choose linear. // std::greater, choose linear.
// - Otherwise, choose binary. // - Otherwise, choose binary.
// TODO(ezb): Might make sense to add condition(s) based on node-size. // TODO(ezb): Might make sense to add condition(s) based on node-size.
using use_linear_search = std::integral_constant< using use_linear_search = std::integral_constant<
bool, bool,
std::is_arithmetic<key_type>::value && has_linear_node_search_preference<key_compare>::value
? prefers_linear_node_search<key_compare>::value
: has_linear_node_search_preference<key_type>::value
? prefers_linear_node_search<key_type>::value
: std::is_arithmetic<key_type>::value &&
(std::is_same<std::less<key_type>, key_compare>::value || (std::is_same<std::less<key_type>, key_compare>::value ||
std::is_same<std::greater<key_type>, key_compare>::value)>; std::is_same<std::greater<key_type>,
key_compare>::value)>;
// This class is organized by gtl::Layout as if it had the following // This class is organized by gtl::Layout as if it had the following
// structure: // structure:
......
...@@ -542,7 +542,7 @@ class StatusOr : private internal_statusor::StatusOrData<T>, ...@@ -542,7 +542,7 @@ class StatusOr : private internal_statusor::StatusOrData<T>,
// StatusOr<T>::value_or() // StatusOr<T>::value_or()
// //
// Returns the current value of `this->ok() == true`. Otherwise constructs a // Returns the current value if `this->ok() == true`. Otherwise constructs a
// value using the provided `default_value`. // value using the provided `default_value`.
// //
// Unlike `value`, this function returns by value, copying the current value // Unlike `value`, this function returns by value, copying the current value
......
...@@ -416,16 +416,10 @@ class civil_time { ...@@ -416,16 +416,10 @@ class civil_time {
// Assigning arithmetic. // Assigning arithmetic.
CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept { CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
f_ = step(T{}, f_, n); return *this = *this + n;
return *this;
} }
CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept { CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
if (n != (std::numeric_limits<diff_t>::min)()) { return *this = *this - n;
f_ = step(T{}, f_, -n);
} else {
f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
}
return *this;
} }
CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; } CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
CONSTEXPR_M civil_time operator++(int) noexcept { CONSTEXPR_M civil_time operator++(int) noexcept {
...@@ -442,13 +436,15 @@ class civil_time { ...@@ -442,13 +436,15 @@ class civil_time {
// Binary arithmetic operators. // Binary arithmetic operators.
friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept { friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
return a += n; return civil_time(step(T{}, a.f_, n));
} }
friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept { friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
return a += n; return a + n;
} }
friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept { friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
return a -= n; return n != (std::numeric_limits<diff_t>::min)()
? civil_time(step(T{}, a.f_, -n))
: civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
} }
friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept { friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
return difference(T{}, lhs.f_, rhs.f_); return difference(T{}, lhs.f_, rhs.f_);
......
...@@ -18,4 +18,5 @@ ...@@ -18,4 +18,5 @@
readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016" readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016"
readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008" readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008" readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015"
readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018"
#!/bin/bash
#
# Copyright 2020 The Abseil Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script that can be invoked to test abseil-cpp in a hermetic environment
# using a Docker image on Linux. You must have Docker installed to use this
# script.
set -euox pipefail
if [[ -z ${ABSEIL_ROOT:-} ]]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
if [[ -z ${STD:-} ]]; then
STD="c++11 c++14"
fi
if [[ -z ${COMPILATION_MODE:-} ]]; then
COMPILATION_MODE="fastbuild opt"
fi
if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
fi
source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
readonly DOCKER_CONTAINER=${LINUX_GCC_FLOOR_CONTAINER}
# USE_BAZEL_CACHE=1 only works on Kokoro.
# Without access to the credentials this won't work.
if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
# Bazel doesn't track changes to tools outside of the workspace
# (e.g. /usr/bin/gcc), so by appending the docker container to the
# remote_http_cache url, we make changes to the container part of
# the cache key. Hashing the key is to make it shorter and url-safe.
container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
fi
# Avoid depending on external sites like GitHub by checking --distdir for
# external dependencies first.
# https://docs.bazel.build/versions/master/guide.html#distdir
if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
fi
for std in ${STD}; do
for compilation_mode in ${COMPILATION_MODE}; do
for exceptions_mode in ${EXCEPTIONS_MODE}; do
echo "--------------------------------------------------------------------"
time docker run \
--volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
-e CC="/usr/local/bin/gcc" \
-e BAZEL_CXXOPTS="-std=${std}" \
${DOCKER_EXTRA_ARGS:-} \
${DOCKER_CONTAINER} \
/usr/local/bin/bazel test ... \
--compilation_mode="${compilation_mode}" \
--copt="${exceptions_mode}" \
--copt=-Werror \
--define="absl=1" \
--keep_going \
--show_timestamps \
--test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
--test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
--test_output=errors \
--test_tag_filters=-benchmark \
${BAZEL_EXTRA_ARGS:-}
done
done
done
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment