From 1d31b5c365e975d3c8a8f90492c3d9de35ef024f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 3 Jun 2020 14:03:13 -0700 Subject: Export of internal Abseil changes -- 9e8b4a286d70df9487bff080816bd07ae38af5f8 by Evan Brown : Add btree_node::transfer_n/transfer_n_backward and replace usage of uninitialized_move_n and value_destroy_n. PiperOrigin-RevId: 314600027 -- 6c452aa1ee7e46ab941ba7d1fa636da8ea3d7370 by Laramie Leavitt : Remove the MockingBitGenBase base class in favor of type-erasure in BitGenRef. In Abseil random, mocking was split across two different classes, MockingBitGenBase and MockingBitGen. This split existed because Google Mock is a test-only library that we don't link into production, so MockingBitGenBase provided a low-overhead scaffold used to lookup mocks when in test code, but which is unused in production code. That has been replaced by type-erasure which looks for a method named CallImpl with the correct signature. Weaken the coupling between MockingBitGen, DistributionCaller, and MockOverloadSet. Rename CallImpl to InvokeMock() Previously, the implementation of DistributionCaller was also split across different files using explicit instantiation of the DistributionCaller struct and some details in the Mocking classes. Now Distribution caller uses the presence of the InvokeMock() method to choose whether to use the mockable call path or the default call path. PiperOrigin-RevId: 314584095 -- 07853c47dc98698d67d65a3b9b662a65ab9def0a by Abseil Team : Add PC / backtrace / symbolization support for Apple platforms. Full backtrace support requires iOS 9+ PiperOrigin-RevId: 314415072 -- 43889f17a132b31f6558c6482721cbbc776128fd by Gennadiy Rozental : Consolidate all reflection interface in the new module 'reflection' and expose interface to locate reflection handle by name. PiperOrigin-RevId: 314390358 GitOrigin-RevId: 9e8b4a286d70df9487bff080816bd07ae38af5f8 Change-Id: I8e0910437740cf9ea9da5000adddfcef127e1158 --- absl/flags/reflection.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 absl/flags/reflection.h (limited to 'absl/flags/reflection.h') diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h new file mode 100644 index 00000000..e8e24f68 --- /dev/null +++ b/absl/flags/reflection.h @@ -0,0 +1,47 @@ +// +// 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. +// +// ----------------------------------------------------------------------------- +// File: reflection.h +// ----------------------------------------------------------------------------- +// +// This file defines the routines to access and operate on an Abseil Flag's +// reflection handle. + +#ifndef ABSL_FLAGS_REFLECTION_H_ +#define ABSL_FLAGS_REFLECTION_H_ + +#include + +#include "absl/base/config.h" +#include "absl/flags/commandlineflag.h" +#include "absl/flags/internal/commandlineflag.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// FindCommandLineFlag() +// +// Returns the reflection handle of an Abseil flag of the specified name, or +// `nullptr` if not found. This function will emit a warning if the name of a +// 'retired' flag is specified. +CommandLineFlag* FindCommandLineFlag(absl::string_view name); + +//----------------------------------------------------------------------------- + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_FLAGS_REFLECTION_H_ -- cgit v1.2.3 From a8b03d90e0afe03fefa16d4a871ece344a5d52ad Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 4 Jun 2020 14:05:55 -0700 Subject: Export of internal Abseil changes -- 5b9d5ce21074c0541432555d383d1b9c5898b553 by Gennadiy Rozental : Convert FlagSaver into public API PiperOrigin-RevId: 314799739 -- 5f796c9862b1177f161f4b10fe1a84698ebbb5cf by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 314786474 -- 67f2ae0ac5ae73bcd9d57a058ac4fea8fc1243ba by Gennadiy Rozental : Makes sure stacktrace_generic is only used with glibc. Fixes #701 PiperOrigin-RevId: 314726944 -- efb1ef3636b0698b79d3ee3590f12c4dff32a3cb by Samuel Benzaquen : Take the bits into account when reserving the space for the operation, not just the exponent. PiperOrigin-RevId: 314622744 GitOrigin-RevId: 5b9d5ce21074c0541432555d383d1b9c5898b553 Change-Id: I080a5e333e2dc1545b5aa0417882f7ac7116a20c --- absl/base/internal/low_level_scheduling.h | 5 +++ absl/debugging/internal/stacktrace_config.h | 2 +- absl/flags/commandlineflag_test.cc | 4 +-- absl/flags/flag_test.cc | 2 +- absl/flags/internal/registry.h | 25 -------------- absl/flags/internal/usage_test.cc | 2 +- absl/flags/parse_test.cc | 2 +- absl/flags/reflection.cc | 21 +++--------- absl/flags/reflection.h | 38 ++++++++++++++++++++++ absl/flags/reflection_test.cc | 4 +-- absl/strings/internal/str_format/convert_test.cc | 6 ++++ .../internal/str_format/float_conversion.cc | 12 +++---- absl/synchronization/mutex.cc | 7 ++++ 13 files changed, 75 insertions(+), 55 deletions(-) (limited to 'absl/flags/reflection.h') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 961cc981..7c52d48c 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -77,6 +80,8 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly white-listed. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h index 8caa97c0..d5cc1740 100644 --- a/absl/debugging/internal/stacktrace_config.h +++ b/absl/debugging/internal/stacktrace_config.h @@ -61,7 +61,7 @@ # elif defined(__aarch64__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_aarch64-inl.inc" -# elif defined(__arm__) +#elif defined(__arm__) && defined(__GLIBC__) // Note: When using glibc this may require -funwind-tables to function properly. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc index cc8eae91..c5afff61 100644 --- a/absl/flags/commandlineflag_test.cc +++ b/absl/flags/commandlineflag_test.cc @@ -47,7 +47,7 @@ class CommandLineFlagTest : public testing::Test { absl::SetFlagsUsageConfig(default_config); } - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: @@ -60,7 +60,7 @@ class CommandLineFlagTest : public testing::Test { return std::string(fname); } - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 0c88e24a..2eb2ba71 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -81,7 +81,7 @@ class FlagTest : public testing::Test { #endif return std::string(fname); } - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; struct S1 { diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 1e655a3e..c72eebe2 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -89,31 +89,6 @@ inline bool RetiredFlag(const char* flag_name) { return flags_internal::Retire(flag_name, base_internal::FastTypeId()); } -//----------------------------------------------------------------------------- -// Saves the states (value, default value, whether the user has set -// the flag, registered validators, etc) of all flags, and restores -// them when the FlagSaver is destroyed. -// -// This class is thread-safe. However, its destructor writes to -// exactly the set of flags that have changed value during its -// lifetime, so concurrent _direct_ access to those flags -// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. - -class FlagSaver { - public: - FlagSaver(); - ~FlagSaver(); - - FlagSaver(const FlagSaver&) = delete; - void operator=(const FlagSaver&) = delete; - - // Prevents saver from restoring the saved state of flags. - void Ignore(); - - private: - class FlagSaverImpl* impl_; // we use pimpl here to keep API steady -}; - } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index 46f85b55..6e583fbe 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -89,7 +89,7 @@ class UsageReportingTest : public testing::Test { } private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc index 1ab87690..67ae8aad 100644 --- a/absl/flags/parse_test.cc +++ b/absl/flags/parse_test.cc @@ -208,7 +208,7 @@ using testing::ElementsAreArray; class ParseTest : public testing::Test { private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 02bb6c2e..5fc945f2 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -65,7 +65,8 @@ class FlagRegistry { static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: - friend class FlagSaverImpl; // reads all the flags in order to copy them + friend class flags_internal::FlagSaverImpl; // reads all the flags in order + // to copy them friend void ForEachFlagUnlocked( std::function visitor); @@ -249,15 +250,6 @@ bool Retire(const char* name, FlagFastTypeId type_id) { // -------------------------------------------------------------------- -// FlagSaver -// FlagSaverImpl -// This class stores the states of all flags at construct time, -// and restores all flags to that state at destruct time. -// Its major implementation challenge is that it never modifies -// pointers in the 'main' registry, so global FLAG_* vars always -// point to the right place. -// -------------------------------------------------------------------- - class FlagSaverImpl { public: FlagSaverImpl() = default; @@ -288,11 +280,10 @@ class FlagSaverImpl { backup_registry_; }; -FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } +} // namespace flags_internal -void FlagSaver::Ignore() { - delete impl_; - impl_ = nullptr; +FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) { + impl_->SaveFromRegistry(); } FlagSaver::~FlagSaver() { @@ -304,8 +295,6 @@ FlagSaver::~FlagSaver() { // -------------------------------------------------------------------- -} // namespace flags_internal - CommandLineFlag* FindCommandLineFlag(absl::string_view name) { if (name.empty()) return nullptr; flags_internal::FlagRegistry& registry = diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h index e8e24f68..045f9784 100644 --- a/absl/flags/reflection.h +++ b/absl/flags/reflection.h @@ -31,6 +31,9 @@ namespace absl { ABSL_NAMESPACE_BEGIN +namespace flags_internal { +class FlagSaverImpl; +} // namespace flags_internal // FindCommandLineFlag() // @@ -39,6 +42,41 @@ ABSL_NAMESPACE_BEGIN // 'retired' flag is specified. CommandLineFlag* FindCommandLineFlag(absl::string_view name); +//------------------------------------------------------------------------------ +// FlagSaver +//------------------------------------------------------------------------------ +// +// A FlagSaver object stores the state of flags in the scope where the FlagSaver +// is defined, allowing modification of those flags within that scope and +// automatic restoration of the flags to their previous state upon leaving the +// scope. +// +// A FlagSaver can be used within tests to temporarily change the test +// environment and restore the test case to its previous state. +// +// Example: +// +// void MyFunc() { +// absl::FlagSaver fs; +// ... +// absl::SetFlag(FLAGS_myFlag, otherValue); +// ... +// } // scope of FlagSaver left, flags return to previous state +// +// This class is thread-safe. + +class FlagSaver { + public: + FlagSaver(); + ~FlagSaver(); + + FlagSaver(const FlagSaver&) = delete; + void operator=(const FlagSaver&) = delete; + + private: + flags_internal::FlagSaverImpl* impl_; +}; + //----------------------------------------------------------------------------- ABSL_NAMESPACE_END diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc index 2a137bf7..9781e597 100644 --- a/absl/flags/reflection_test.cc +++ b/absl/flags/reflection_test.cc @@ -34,11 +34,11 @@ namespace flags = absl::flags_internal; class ReflectionTest : public testing::Test { protected: - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 20c6229f..0e8535c2 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) { } } + // Regression tests + // + // Using a string literal because not all platforms support hex literals or it + // might be out of range. + doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr)); + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index a761a5a5..10e46954 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -224,13 +224,13 @@ class FractionalDigitGenerator { // This function will allocate enough stack space to perform the conversion. static void RunConversion( uint128 v, int exp, absl::FunctionRef f) { + using Limits = std::numeric_limits; assert(-exp < 0); - assert(-exp >= std::numeric_limits::min_exponent - 128); - static_assert( - StackArray::kMaxCapacity >= - (128 - std::numeric_limits::min_exponent + 31) / 32, - ""); - StackArray::RunWithCapacity((exp + 31) / 32, + assert(-exp >= Limits::min_exponent - 128); + static_assert(StackArray::kMaxCapacity >= + (Limits::digits + 128 - Limits::min_exponent + 31) / 32, + ""); + StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32, [=](absl::Span input) { f(FractionalDigitGenerator(input, v, exp)); }); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 1f8a696e..36c93d5f 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -58,6 +58,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -1108,6 +1109,7 @@ void Mutex::TryRemove(PerThreadSynch *s) { // on the mutex queue. In this case, remove "s" from the queue and return // true, otherwise return false. ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { if (!DecrementSynchSem(this, s, s->waitp->timeout)) { // After a timeout, we go into a spin loop until we remove ourselves @@ -1897,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2016,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2331,6 +2335,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2429,6 +2434,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2589,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; -- cgit v1.2.3 From fbf0fdab62ac6fcc72b935d505f6837e0884fdc3 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 20 Aug 2020 08:54:55 -0700 Subject: Export of internal Abseil changes -- 9f746b79e16d36dba908ed9e2a586d890fe54acc by Derek Mauro : Remove the Bazel mirror URL that we use in our WORKSPACE file This doesn't appear to be supported. We use --distdir caching in our tests. PiperOrigin-RevId: 327634738 -- e1f6f54830c415fc8bb8dc14483fae4cf9713d75 by Abseil Team : Removing comments following license() rules as they are rarely useful, redundant with LICENSE files, and tend to fall out of date. PiperOrigin-RevId: 327504063 -- b59c076638a57a74a3f8475f1dee8b536e32a15f by Gennadiy Rozental : Change GetAllFlags API to return a collection of mutable flag handles. This will make this interface on par with FindCommandLineFlag and allow to call CommandLineFlag::ParseFrom on the handle returned by GetAllFlags. PiperOrigin-RevId: 327499084 -- bbf56b3c4a1d908d95e5a52aba38b1984151efff by Gennadiy Rozental : Make raw_hash_set compile when AllocTraits::propagate_on_container_swap is false. PiperOrigin-RevId: 327371107 -- 837f62c85ea65c1d6b847a75816198c625fe62ff by Abseil Team : On macOS, `mem_alloc` is defined like this: rpc/types.h:86:#define mem_alloc(bsize) calloc(1, bsize) So if that file is included before container_memory.h, the variable mem_alloc may never get defined. This is fixed by using a different name. PiperOrigin-RevId: 327360224 -- aa8f5528382c0d01239ce75b645723aaf7e1ef46 by Gennadiy Rozental : Release of absl::GetAllFlags API. PiperOrigin-RevId: 327275943 GitOrigin-RevId: 9f746b79e16d36dba908ed9e2a586d890fe54acc Change-Id: I99c5c87dd1712bf8df9a52397b0c1e400a3c3447 --- WORKSPACE | 1 - absl/algorithm/BUILD.bazel | 2 +- absl/base/BUILD.bazel | 2 +- absl/container/BUILD.bazel | 2 +- absl/container/internal/container_memory.h | 14 +++-- absl/container/internal/raw_hash_set.h | 28 ++++++--- .../internal/raw_hash_set_allocator_test.cc | 71 ++++++++++++++++++++++ absl/debugging/BUILD.bazel | 2 +- absl/flags/BUILD.bazel | 4 +- absl/flags/CMakeLists.txt | 4 +- absl/flags/reflection.cc | 10 +++ absl/flags/reflection.h | 7 ++- absl/flags/reflection_test.cc | 31 ++++++++++ absl/functional/BUILD.bazel | 2 +- absl/hash/BUILD.bazel | 2 +- absl/memory/BUILD.bazel | 2 +- absl/meta/BUILD.bazel | 2 +- absl/numeric/BUILD.bazel | 2 +- absl/random/internal/BUILD.bazel | 2 +- absl/status/BUILD.bazel | 2 +- absl/synchronization/BUILD.bazel | 2 +- absl/time/BUILD.bazel | 2 +- absl/types/BUILD.bazel | 2 +- absl/utility/BUILD.bazel | 2 +- 24 files changed, 168 insertions(+), 32 deletions(-) (limited to 'absl/flags/reflection.h') diff --git a/WORKSPACE b/WORKSPACE index 96338199..0b533562 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -39,7 +39,6 @@ http_archive( sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d", strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa", urls = [ - "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip", "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip", ], ) diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel index 229cd713..a3002b7d 100644 --- a/absl/algorithm/BUILD.bazel +++ b/absl/algorithm/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "algorithm", diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 2c4887b3..9d96abeb 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "atomic_hook", diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index cca5d441..8e72ad03 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "compressed_tuple", diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index d02c576d..e67529ec 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -57,8 +57,11 @@ void* Allocate(Alloc* alloc, size_t n) { using M = AlignedType; using A = typename absl::allocator_traits::template rebind_alloc; using AT = typename absl::allocator_traits::template rebind_traits; - A mem_alloc(*alloc); - void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M)); + // On macOS, "mem_alloc" is a #define with one argument defined in + // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it + // with the "foo(bar)" syntax. + A my_mem_alloc(*alloc); + void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M)); assert(reinterpret_cast(p) % Alignment == 0 && "allocator does not respect alignment"); return p; @@ -73,8 +76,11 @@ void Deallocate(Alloc* alloc, void* p, size_t n) { using M = AlignedType; using A = typename absl::allocator_traits::template rebind_alloc; using AT = typename absl::allocator_traits::template rebind_traits; - A mem_alloc(*alloc); - AT::deallocate(mem_alloc, static_cast(p), + // On macOS, "mem_alloc" is a #define with one argument defined in + // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it + // with the "foo(bar)" syntax. + A my_mem_alloc(*alloc); + AT::deallocate(my_mem_alloc, static_cast(p), (n + sizeof(M) - 1) / sizeof(M)); } diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 48a1a8c6..130da13c 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -122,6 +122,16 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace container_internal { +template +void SwapAlloc(AllocType& lhs, AllocType& rhs, + std::true_type /* propagate_on_container_swap */) { + using std::swap; + swap(lhs, rhs); +} +template +void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/, + std::false_type /* propagate_on_container_swap */) {} + template class probe_seq { public: @@ -169,10 +179,14 @@ struct IsDecomposable< // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it. template -constexpr bool IsNoThrowSwappable() { +constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) { using std::swap; return noexcept(swap(std::declval(), std::declval())); } +template +constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) { + return false; +} template int TrailingZeros(T x) { @@ -1231,8 +1245,8 @@ class raw_hash_set { void swap(raw_hash_set& that) noexcept( IsNoThrowSwappable() && IsNoThrowSwappable() && - (!AllocTraits::propagate_on_container_swap::value || - IsNoThrowSwappable())) { + IsNoThrowSwappable( + typename AllocTraits::propagate_on_container_swap{})) { using std::swap; swap(ctrl_, that.ctrl_); swap(slots_, that.slots_); @@ -1242,12 +1256,8 @@ class raw_hash_set { swap(hash_ref(), that.hash_ref()); swap(eq_ref(), that.eq_ref()); swap(infoz_, that.infoz_); - if (AllocTraits::propagate_on_container_swap::value) { - swap(alloc_ref(), that.alloc_ref()); - } else { - // If the allocators do not compare equal it is officially undefined - // behavior. We choose to do nothing. - } + SwapAlloc(alloc_ref(), that.alloc_ref(), + typename AllocTraits::propagate_on_container_swap{}); } void rehash(size_t n) { diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc index 7ac4b9f7..1a036085 100644 --- a/absl/container/internal/raw_hash_set_allocator_test.cc +++ b/absl/container/internal/raw_hash_set_allocator_test.cc @@ -424,6 +424,77 @@ TEST_F(PropagateOnAll, Swap) { EXPECT_EQ(0, it->num_copies()); } +// This allocator is similar to std::pmr::polymorphic_allocator. +// Note the disabled assignment. +template +class PAlloc { + template + friend class PAlloc; + + public: + // types + using value_type = T; + + // traits + using propagate_on_container_swap = std::false_type; + + PAlloc() noexcept = default; + explicit PAlloc(size_t id) noexcept : id_(id) {} + PAlloc(const PAlloc&) noexcept = default; + PAlloc& operator=(const PAlloc&) noexcept = delete; + + template + PAlloc(const PAlloc& that) noexcept : id_(that.id_) {} // NOLINT + + template + struct rebind { + using other = PAlloc; + }; + + constexpr PAlloc select_on_container_copy_construction() const { return {}; } + + // public member functions + T* allocate(size_t) { return new T; } + void deallocate(T* p, size_t) { delete p; } + + friend bool operator==(const PAlloc& a, const PAlloc& b) { + return a.id_ == b.id_; + } + friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); } + + private: + size_t id_ = std::numeric_limits::max(); +}; + +TEST(NoPropagateOn, Swap) { + using PA = PAlloc; + using Table = raw_hash_set, PA>; + + Table t1(PA{1}), t2(PA{2}); + swap(t1, t2); + EXPECT_EQ(t1.get_allocator(), PA(1)); + EXPECT_EQ(t2.get_allocator(), PA(2)); +} + +TEST(NoPropagateOn, CopyConstruct) { + using PA = PAlloc; + using Table = raw_hash_set, PA>; + + Table t1(PA{1}), t2(t1); + EXPECT_EQ(t1.get_allocator(), PA(1)); + EXPECT_EQ(t2.get_allocator(), PA()); +} + +TEST(NoPropagateOn, Assignment) { + using PA = PAlloc; + using Table = raw_hash_set, PA>; + + Table t1(PA{1}), t2(PA{2}); + t1 = t2; + EXPECT_EQ(t1.get_allocator(), PA(1)); + EXPECT_EQ(t2.get_allocator(), PA(2)); +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 9098ca4a..86faac9b 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -26,7 +26,7 @@ package( default_visibility = ["//visibility:public"], ) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "stacktrace", diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 92bd4f15..62fb9a8b 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "path_util", @@ -179,6 +179,7 @@ cc_library( ":private_handle_accessor", "//absl/base:config", "//absl/base:core_headers", + "//absl/container:flat_hash_map", "//absl/strings", "//absl/synchronization", ], @@ -464,6 +465,7 @@ cc_test( ":flag", ":marshalling", ":reflection", + ":usage_internal", "//absl/memory", "//absl/strings", "@com_google_googletest//:gtest_main", diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index 343774de..28bd5a85 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -165,6 +165,7 @@ absl_cc_library( absl::flags_config absl::strings absl::synchronization + absl::flat_hash_map ) # Internal-only target, do not depend on directly. @@ -407,9 +408,10 @@ absl_cc_test( absl::flags_commandlineflag_internal absl::flags absl::flags_reflection + absl::flags_usage absl::memory absl::strings - gtest_main + gmock_main ) absl_cc_test( diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index e4145b34..d7060221 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -303,5 +303,15 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) { return registry.FindFlagLocked(name); } +// -------------------------------------------------------------------- + +absl::flat_hash_map GetAllFlags() { + absl::flat_hash_map res; + flags_internal::ForEachFlag([&](CommandLineFlag& flag) { + res.insert({flag.Name(), &flag}); + }); + return res; +} + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h index 045f9784..4ce0ab6c 100644 --- a/absl/flags/reflection.h +++ b/absl/flags/reflection.h @@ -26,6 +26,7 @@ #include #include "absl/base/config.h" +#include "absl/container/flat_hash_map.h" #include "absl/flags/commandlineflag.h" #include "absl/flags/internal/commandlineflag.h" @@ -40,7 +41,11 @@ class FlagSaverImpl; // Returns the reflection handle of an Abseil flag of the specified name, or // `nullptr` if not found. This function will emit a warning if the name of a // 'retired' flag is specified. -CommandLineFlag* FindCommandLineFlag(absl::string_view name); +absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name); + +// Returns current state of the Flags registry in a form of mapping from flag +// name to a flag reflection handle. +absl::flat_hash_map GetAllFlags(); //------------------------------------------------------------------------------ // FlagSaver diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc index 2da0a0ec..1a1dcb4a 100644 --- a/absl/flags/reflection_test.cc +++ b/absl/flags/reflection_test.cc @@ -18,7 +18,9 @@ #include #include +#include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/flags/declare.h" #include "absl/flags/flag.h" #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/marshalling.h" @@ -30,6 +32,8 @@ ABSL_FLAG(int, int_flag, 1, "int_flag help"); ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help"); ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help"); +ABSL_DECLARE_FLAG(bool, help); + namespace { namespace flags = absl::flags_internal; @@ -61,6 +65,33 @@ TEST_F(ReflectionTest, TestFindCommandLineFlag) { // -------------------------------------------------------------------- +TEST_F(ReflectionTest, TestGetAllFlags) { + (void)absl::GetFlag(FLAGS_help); // Force linking of usage flags. + + auto all_flags = absl::GetAllFlags(); + EXPECT_NE(all_flags.find("int_flag"), all_flags.end()); + EXPECT_NE(all_flags.find("bool_retired_flag"), all_flags.end()); + EXPECT_NE(all_flags.find("help"), all_flags.end()); + EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end()); + + std::vector flag_names_first_attempt; + auto all_flags_1 = absl::GetAllFlags(); + for (auto f : all_flags_1) { + flag_names_first_attempt.push_back(f.first); + } + + std::vector flag_names_second_attempt; + auto all_flags_2 = absl::GetAllFlags(); + for (auto f : all_flags_2) { + flag_names_second_attempt.push_back(f.first); + } + + EXPECT_THAT(flag_names_first_attempt, + ::testing::UnorderedElementsAreArray(flag_names_second_attempt)); +} + +// -------------------------------------------------------------------- + struct CustomUDT { CustomUDT() : a(1), b(1) {} CustomUDT(int a_, int b_) : a(a_), b(b_) {} diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel index 432546ce..ebd9b99b 100644 --- a/absl/functional/BUILD.bazel +++ b/absl/functional/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "bind_front", diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel index 6c77f1a1..5b1e2d01 100644 --- a/absl/hash/BUILD.bazel +++ b/absl/hash/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "hash", diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel index 2ba9d7cb..d2824a05 100644 --- a/absl/memory/BUILD.bazel +++ b/absl/memory/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "memory", diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel index c06d2d97..5585fcca 100644 --- a/absl/meta/BUILD.bazel +++ b/absl/meta/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "type_traits", diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel index da3af4d0..f808f5da 100644 --- a/absl/numeric/BUILD.bazel +++ b/absl/numeric/BUILD.bazel @@ -22,7 +22,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "int128", diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index 000cc45b..8485e28b 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -30,7 +30,7 @@ package(default_visibility = [ "//absl/random:__pkg__", ]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "traits", diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel index c4c5e497..81fa46c2 100644 --- a/absl/status/BUILD.bazel +++ b/absl/status/BUILD.bazel @@ -26,7 +26,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "status", diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index 1a5c02ab..4d4d6806 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) # Internal data structure for efficiently detecting mutex dependency cycles cc_library( diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel index 1d69f598..991241a0 100644 --- a/absl/time/BUILD.bazel +++ b/absl/time/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "time", diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index 102affaf..83be9360 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -23,7 +23,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "any", diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel index 6881f939..02b2c407 100644 --- a/absl/utility/BUILD.bazel +++ b/absl/utility/BUILD.bazel @@ -24,7 +24,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "utility", -- cgit v1.2.3 From 5bf048b8425cc0a342e4647932de19e25ffd6ad7 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 26 Oct 2020 09:50:44 -0700 Subject: Export of internal Abseil changes -- 730bb88bee556aa11fa19aa33e1434cb6fa78985 by Evan Brown : Support missing allocator-related constructors in b-tree. See [reference](https://en.cppreference.com/w/cpp/container/set/set). Also use allocator_traits::select_on_container_copy_construction() to get allocator for copy construction. PiperOrigin-RevId: 339058322 -- b6cc121689ae3e452d1db2d66122cb198d25142b by Derek Mauro : Fix more sign-compare warnings PiperOrigin-RevId: 339057920 -- 0e2c62da1dcaf6529abab952bdcc96c6de2d9506 by Abseil Team : Add missing include PiperOrigin-RevId: 339054753 -- d5a9ec2d1e40fe6359e720942e4955009ee415ec by Derek Mauro : Stop disabling sign-compare warnings for non-test targets. Our users complain about these. This does not catch issues in header-only libraries (like btree.h) but we may work on those in the future PiperOrigin-RevId: 338967089 -- 0c062c542a4c61ea0f65d25811827c0858e3adde by Abseil Team : Improve cache-locality for ThreadIdentity and PerThreadSynch. This is a change based on an observation in RPC benchmarks that shows significant cycles being spent in waking up a thread, 99.8% of which was on cache misses. Investigating this a bit more, it turns out to be due to sharing the cache line with the waiter state. To fix this issue, the following changes are introduced: - Reorder fields in PerThreadSync so that it fits in a single cache line The size of this structure was 80 bytes before this change. Note: Manually inspected all booleans to make sure they are not modified by multiple threads concurrently. PiperOrigin-RevId: 338852058 -- a90d6f2b2346385017e32dd8ae1b5ca691a5863f by Derek Mauro : Delete GCC 4.9 test script. It is no longer supported PiperOrigin-RevId: 338779452 -- 7274008d4757e88869110be9db39d03d911ae2b5 by Abseil Team : Fix the usage example in which SetFlag should take a pointer. PiperOrigin-RevId: 338744529 GitOrigin-RevId: 730bb88bee556aa11fa19aa33e1434cb6fa78985 Change-Id: Iff99594c4022e60e482a392d334b376c7ae8883e --- absl/base/internal/thread_identity.h | 79 +++++++++--------- absl/container/btree_test.cc | 95 ++++++++++++++++++++++ absl/container/internal/btree.h | 42 +++++----- absl/container/internal/btree_container.h | 40 +++++++-- absl/copts/GENERATED_AbseilCopts.cmake | 3 - absl/copts/GENERATED_copts.bzl | 3 - absl/copts/copts.py | 7 -- absl/debugging/symbolize_elf.inc | 4 +- absl/flags/reflection.h | 2 +- absl/strings/internal/charconv_parse.cc | 12 +-- absl/strings/internal/str_format/bind.cc | 2 +- .../internal/str_format/float_conversion.cc | 2 +- absl/synchronization/internal/graphcycles.cc | 1 + ci/linux_docker_containers.sh | 1 - ci/linux_gcc-4.9_libstdcxx_bazel.sh | 89 -------------------- 15 files changed, 203 insertions(+), 179 deletions(-) delete mode 100755 ci/linux_gcc-4.9_libstdcxx_bazel.sh (limited to 'absl/flags/reflection.h') diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index ceb109b4..c61d1feb 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -32,6 +32,7 @@ #include "absl/base/config.h" #include "absl/base/internal/per_thread_tls.h" +#include "absl/base/optimization.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -69,30 +70,28 @@ struct PerThreadSynch { // is using this PerThreadSynch as a terminator. Its // skip field must not be filled in because the loop // might then skip over the terminator. - - // The wait parameters of the current wait. waitp is null if the - // thread is not waiting. Transitions from null to non-null must - // occur before the enqueue commit point (state = kQueued in - // Enqueue() and CondVarEnqueue()). Transitions from non-null to - // null must occur after the wait is finished (state = kAvailable in - // Mutex::Block() and CondVar::WaitCommon()). This field may be - // changed only by the thread that describes this PerThreadSynch. A - // special case is Fer(), which calls Enqueue() on another thread, - // but with an identical SynchWaitParams pointer, thus leaving the - // pointer unchanged. - SynchWaitParams *waitp; - - bool suppress_fatal_errors; // If true, try to proceed even in the face of - // broken invariants. This is used within fatal - // signal handlers to improve the chances of - // debug logging information being output - // successfully. - - intptr_t readers; // Number of readers in mutex. - int priority; // Priority of thread (updated every so often). - - // When priority will next be read (cycles). - int64_t next_priority_read_cycles; + bool wake; // This thread is to be woken from a Mutex. + // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the + // waiter is waiting on the mutex as part of a CV Wait or Mutex Await. + // + // The value of "x->cond_waiter" is meaningless if "x" is not on a + // Mutex waiter list. + bool cond_waiter; + bool maybe_unlocking; // Valid at head of Mutex waiter queue; + // true if UnlockSlow could be searching + // for a waiter to wake. Used for an optimization + // in Enqueue(). true is always a valid value. + // Can be reset to false when the unlocker or any + // writer releases the lock, or a reader fully + // releases the lock. It may not be set to false + // by a reader that decrements the count to + // non-zero. protected by mutex spinlock + bool suppress_fatal_errors; // If true, try to proceed even in the face + // of broken invariants. This is used within + // fatal signal handlers to improve the + // chances of debug logging information being + // output successfully. + int priority; // Priority of thread (updated every so often). // State values: // kAvailable: This PerThreadSynch is available. @@ -111,30 +110,30 @@ struct PerThreadSynch { }; std::atomic state; - bool maybe_unlocking; // Valid at head of Mutex waiter queue; - // true if UnlockSlow could be searching - // for a waiter to wake. Used for an optimization - // in Enqueue(). true is always a valid value. - // Can be reset to false when the unlocker or any - // writer releases the lock, or a reader fully releases - // the lock. It may not be set to false by a reader - // that decrements the count to non-zero. - // protected by mutex spinlock + // The wait parameters of the current wait. waitp is null if the + // thread is not waiting. Transitions from null to non-null must + // occur before the enqueue commit point (state = kQueued in + // Enqueue() and CondVarEnqueue()). Transitions from non-null to + // null must occur after the wait is finished (state = kAvailable in + // Mutex::Block() and CondVar::WaitCommon()). This field may be + // changed only by the thread that describes this PerThreadSynch. A + // special case is Fer(), which calls Enqueue() on another thread, + // but with an identical SynchWaitParams pointer, thus leaving the + // pointer unchanged. + SynchWaitParams* waitp; - bool wake; // This thread is to be woken from a Mutex. + intptr_t readers; // Number of readers in mutex. - // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the - // waiter is waiting on the mutex as part of a CV Wait or Mutex Await. - // - // The value of "x->cond_waiter" is meaningless if "x" is not on a - // Mutex waiter list. - bool cond_waiter; + // When priority will next be read (cycles). + int64_t next_priority_read_cycles; // Locks held; used during deadlock detection. // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity(). SynchLocksHeld *all_locks; }; +// The instances of this class are allocated in NewThreadIdentity() with an +// alignment of PerThreadSynch::kAlignment. struct ThreadIdentity { // Must be the first member. The Mutex implementation requires that // the PerThreadSynch object associated with each thread is diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc index 7fa5d4f3..4a495067 100644 --- a/absl/container/btree_test.cc +++ b/absl/container/btree_test.cc @@ -2709,6 +2709,101 @@ TEST(Btree, MultiKeyEqualRange) { } } +TEST(Btree, AllocConstructor) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used = 0; + Alloc alloc(&bytes_used); + Set set(alloc); + + set.insert({1, 2, 3}); + + EXPECT_THAT(set, ElementsAre(1, 2, 3)); + EXPECT_GT(bytes_used, set.size() * sizeof(int)); +} + +TEST(Btree, AllocInitializerListConstructor) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used = 0; + Alloc alloc(&bytes_used); + Set set({1, 2, 3}, alloc); + + EXPECT_THAT(set, ElementsAre(1, 2, 3)); + EXPECT_GT(bytes_used, set.size() * sizeof(int)); +} + +TEST(Btree, AllocRangeConstructor) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used = 0; + Alloc alloc(&bytes_used); + std::vector v = {1, 2, 3}; + Set set(v.begin(), v.end(), alloc); + + EXPECT_THAT(set, ElementsAre(1, 2, 3)); + EXPECT_GT(bytes_used, set.size() * sizeof(int)); +} + +TEST(Btree, AllocCopyConstructor) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used1 = 0; + Alloc alloc1(&bytes_used1); + Set set1(alloc1); + + set1.insert({1, 2, 3}); + + int64_t bytes_used2 = 0; + Alloc alloc2(&bytes_used2); + Set set2(set1, alloc2); + + EXPECT_THAT(set1, ElementsAre(1, 2, 3)); + EXPECT_THAT(set2, ElementsAre(1, 2, 3)); + EXPECT_GT(bytes_used1, set1.size() * sizeof(int)); + EXPECT_EQ(bytes_used1, bytes_used2); +} + +TEST(Btree, AllocMoveConstructor_SameAlloc) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used = 0; + Alloc alloc(&bytes_used); + Set set1(alloc); + + set1.insert({1, 2, 3}); + + const int64_t original_bytes_used = bytes_used; + EXPECT_GT(original_bytes_used, set1.size() * sizeof(int)); + + Set set2(std::move(set1), alloc); + + EXPECT_THAT(set2, ElementsAre(1, 2, 3)); + EXPECT_EQ(bytes_used, original_bytes_used); +} + +TEST(Btree, AllocMoveConstructor_DifferentAlloc) { + using Alloc = CountingAllocator; + using Set = absl::btree_set, Alloc>; + int64_t bytes_used1 = 0; + Alloc alloc1(&bytes_used1); + Set set1(alloc1); + + set1.insert({1, 2, 3}); + + const int64_t original_bytes_used = bytes_used1; + EXPECT_GT(original_bytes_used, set1.size() * sizeof(int)); + + int64_t bytes_used2 = 0; + Alloc alloc2(&bytes_used2); + Set set2(std::move(set1), alloc2); + + EXPECT_THAT(set2, ElementsAre(1, 2, 3)); + // We didn't free these bytes allocated by `set1` yet. + EXPECT_EQ(bytes_used1, original_bytes_used); + EXPECT_EQ(bytes_used2, original_bytes_used); +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index a82b5177..8547d68e 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -1141,21 +1141,35 @@ class btree { // before this method is called. This method is used in copy construction, // copy assignment, and move assignment. template - void copy_or_move_values_in_order(Btree *other); + void copy_or_move_values_in_order(Btree &other); // Validates that various assumptions/requirements are true at compile time. constexpr static bool static_assert_validation(); public: - btree(const key_compare &comp, const allocator_type &alloc); + btree(const key_compare &comp, const allocator_type &alloc) + : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {} - btree(const btree &other); + btree(const btree &other) : btree(other, other.allocator()) {} + btree(const btree &other, const allocator_type &alloc) + : btree(other.key_comp(), alloc) { + copy_or_move_values_in_order(other); + } btree(btree &&other) noexcept : root_(std::move(other.root_)), rightmost_(absl::exchange(other.rightmost_, EmptyNode())), size_(absl::exchange(other.size_, 0)) { other.mutable_root() = EmptyNode(); } + btree(btree &&other, const allocator_type &alloc) + : btree(other.key_comp(), alloc) { + if (alloc == other.allocator()) { + swap(other); + } else { + // Move values from `other` one at a time when allocators are different. + copy_or_move_values_in_order(other); + } + } ~btree() { // Put static_asserts in destructor to avoid triggering them before the type @@ -1851,7 +1865,7 @@ void btree_iterator::decrement_slow() { // btree methods template template -void btree

::copy_or_move_values_in_order(Btree *other) { +void btree

::copy_or_move_values_in_order(Btree &other) { static_assert(std::is_same::value || std::is_same::value, "Btree type must be same or const."); @@ -1859,11 +1873,11 @@ void btree

::copy_or_move_values_in_order(Btree *other) { // We can avoid key comparisons because we know the order of the // values is the same order we'll store them in. - auto iter = other->begin(); - if (iter == other->end()) return; + auto iter = other.begin(); + if (iter == other.end()) return; insert_multi(maybe_move_from_iterator(iter)); ++iter; - for (; iter != other->end(); ++iter) { + for (; iter != other.end(); ++iter) { // If the btree is not empty, we can just insert the new value at the end // of the tree. internal_emplace(end(), maybe_move_from_iterator(iter)); @@ -1901,16 +1915,6 @@ constexpr bool btree

::static_assert_validation() { return true; } -template -btree

::btree(const key_compare &comp, const allocator_type &alloc) - : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {} - -template -btree

::btree(const btree &other) - : btree(other.key_comp(), other.allocator()) { - copy_or_move_values_in_order(&other); -} - template template auto btree

::equal_range(const K &key) -> std::pair { @@ -2068,7 +2072,7 @@ auto btree

::operator=(const btree &other) -> btree & { *mutable_allocator() = other.allocator(); } - copy_or_move_values_in_order(&other); + copy_or_move_values_in_order(other); } return *this; } @@ -2098,7 +2102,7 @@ auto btree

::operator=(btree &&other) noexcept -> btree & { // comparator while moving the values so we can't swap the key // comparators. *mutable_key_comp() = other.key_comp(); - copy_or_move_values_in_order(&other); + copy_or_move_values_in_order(other); } } } diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h index 2322e7c7..3792bc21 100644 --- a/absl/container/internal/btree_container.h +++ b/absl/container/internal/btree_container.h @@ -23,6 +23,7 @@ #include "absl/base/internal/throw_delegate.h" #include "absl/container/internal/btree.h" // IWYU pragma: export #include "absl/container/internal/common.h" +#include "absl/memory/memory.h" #include "absl/meta/type_traits.h" namespace absl { @@ -68,8 +69,21 @@ class btree_container { explicit btree_container(const key_compare &comp, const allocator_type &alloc = allocator_type()) : tree_(comp, alloc) {} - btree_container(const btree_container &other) = default; - btree_container(btree_container &&other) noexcept = default; + explicit btree_container(const allocator_type &alloc) + : tree_(key_compare(), alloc) {} + + btree_container(const btree_container &other) + : btree_container(other, absl::allocator_traits:: + select_on_container_copy_construction( + other.get_allocator())) {} + btree_container(const btree_container &other, const allocator_type &alloc) + : tree_(other.tree_, alloc) {} + + btree_container(btree_container &&other) noexcept( + std::is_nothrow_move_constructible::value) = default; + btree_container(btree_container &&other, const allocator_type &alloc) + : tree_(std::move(other.tree_), alloc) {} + btree_container &operator=(const btree_container &other) = default; btree_container &operator=(btree_container &&other) noexcept( std::is_nothrow_move_assignable::value) = default; @@ -234,7 +248,7 @@ class btree_set_container : public btree_container { using super_type::super_type; btree_set_container() {} - // Range constructor. + // Range constructors. template btree_set_container(InputIterator b, InputIterator e, const key_compare &comp = key_compare(), @@ -242,12 +256,19 @@ class btree_set_container : public btree_container { : super_type(comp, alloc) { insert(b, e); } + template + btree_set_container(InputIterator b, InputIterator e, + const allocator_type &alloc) + : btree_set_container(b, e, key_compare(), alloc) {} - // Initializer list constructor. + // Initializer list constructors. btree_set_container(std::initializer_list init, const key_compare &comp = key_compare(), const allocator_type &alloc = allocator_type()) : btree_set_container(init.begin(), init.end(), comp, alloc) {} + btree_set_container(std::initializer_list init, + const allocator_type &alloc) + : btree_set_container(init.begin(), init.end(), alloc) {} // Lookup routines. template @@ -535,7 +556,7 @@ class btree_multiset_container : public btree_container { using super_type::super_type; btree_multiset_container() {} - // Range constructor. + // Range constructors. template btree_multiset_container(InputIterator b, InputIterator e, const key_compare &comp = key_compare(), @@ -543,12 +564,19 @@ class btree_multiset_container : public btree_container { : super_type(comp, alloc) { insert(b, e); } + template + btree_multiset_container(InputIterator b, InputIterator e, + const allocator_type &alloc) + : btree_multiset_container(b, e, key_compare(), alloc) {} - // Initializer list constructor. + // Initializer list constructors. btree_multiset_container(std::initializer_list init, const key_compare &comp = key_compare(), const allocator_type &alloc = allocator_type()) : btree_multiset_container(init.begin(), init.end(), comp, alloc) {} + btree_multiset_container(std::initializer_list init, + const allocator_type &alloc) + : btree_multiset_container(init.begin(), init.end(), alloc) {} // Lookup routines. template diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 97bd283e..beb3799e 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -16,7 +16,6 @@ list(APPEND ABSL_CLANG_CL_FLAGS "-Wno-extra-semi-stmt" "-Wno-packed" "-Wno-padded" - "-Wno-sign-compare" "-Wno-float-conversion" "-Wno-float-equal" "-Wno-format-nonliteral" @@ -88,7 +87,6 @@ list(APPEND ABSL_GCC_FLAGS "-Wvla" "-Wwrite-strings" "-Wno-missing-field-initializers" - "-Wno-sign-compare" "-DNOMINMAX" ) @@ -117,7 +115,6 @@ list(APPEND ABSL_LLVM_FLAGS "-Wno-extra-semi-stmt" "-Wno-packed" "-Wno-padded" - "-Wno-sign-compare" "-Wno-float-conversion" "-Wno-float-equal" "-Wno-format-nonliteral" diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index bcdd61ef..ff729d74 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -17,7 +17,6 @@ ABSL_CLANG_CL_FLAGS = [ "-Wno-extra-semi-stmt", "-Wno-packed", "-Wno-padded", - "-Wno-sign-compare", "-Wno-float-conversion", "-Wno-float-equal", "-Wno-format-nonliteral", @@ -89,7 +88,6 @@ ABSL_GCC_FLAGS = [ "-Wvla", "-Wwrite-strings", "-Wno-missing-field-initializers", - "-Wno-sign-compare", "-DNOMINMAX", ] @@ -118,7 +116,6 @@ ABSL_LLVM_FLAGS = [ "-Wno-extra-semi-stmt", "-Wno-packed", "-Wno-padded", - "-Wno-sign-compare", "-Wno-float-conversion", "-Wno-float-equal", "-Wno-format-nonliteral", diff --git a/absl/copts/copts.py b/absl/copts/copts.py index a3437c1b..55b5fb10 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -41,10 +41,6 @@ LLVM_DISABLE_WARNINGS_FLAGS = [ "-Wno-packed", "-Wno-padded", ### - # Google style does not use unsigned integers, though STL containers - # have unsigned types. - "-Wno-sign-compare", - ### "-Wno-float-conversion", "-Wno-float-equal", "-Wno-format-nonliteral", @@ -138,9 +134,6 @@ COPT_VARS = { # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 # Remove when gcc-4.x is no longer supported. "-Wno-missing-field-initializers", - # Google style does not use unsigned integers, though STL containers - # have unsigned types. - "-Wno-sign-compare", # Don't define min and max macros (Build on Windows using gcc) "-DNOMINMAX", ], diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index 7c36fd13..f4d5727b 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -1281,7 +1281,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) { const int phnum = obj->elf_header.e_phnum; const int phentsize = obj->elf_header.e_phentsize; size_t phoff = obj->elf_header.e_phoff; - int num_executable_load_segments = 0; + size_t num_executable_load_segments = 0; for (int j = 0; j < phnum; j++) { ElfW(Phdr) phdr; if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) { @@ -1342,7 +1342,7 @@ const char *Symbolizer::GetSymbol(const void *const pc) { // Note: some binaries have multiple "rx" LOAD segments. We must // find the right one. ElfW(Phdr) *phdr = nullptr; - for (int j = 0; j < obj->phdr.size(); j++) { + for (size_t j = 0; j < obj->phdr.size(); j++) { ElfW(Phdr) &p = obj->phdr[j]; if (p.p_type != PT_LOAD) { // We only expect PT_LOADs. This must be PT_NULL that we didn't diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h index 4ce0ab6c..e6baf5de 100644 --- a/absl/flags/reflection.h +++ b/absl/flags/reflection.h @@ -64,7 +64,7 @@ absl::flat_hash_map GetAllFlags(); // void MyFunc() { // absl::FlagSaver fs; // ... -// absl::SetFlag(FLAGS_myFlag, otherValue); +// absl::SetFlag(&FLAGS_myFlag, otherValue); // ... // } // scope of FlagSaver left, flags return to previous state // diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc index a368845f..8b11868c 100644 --- a/absl/strings/internal/charconv_parse.cc +++ b/absl/strings/internal/charconv_parse.cc @@ -246,8 +246,8 @@ constexpr int DigitMagnitude<16>() { // ConsumeDigits does not protect against overflow on *out; max_digits must // be chosen with respect to type T to avoid the possibility of overflow. template -std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits, - T* out, bool* dropped_nonzero_digit) { +int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out, + bool* dropped_nonzero_digit) { if (base == 10) { assert(max_digits <= std::numeric_limits::digits10); } else if (base == 16) { @@ -282,7 +282,7 @@ std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits, *dropped_nonzero_digit = true; } *out = accumulator; - return begin - original_begin; + return static_cast(begin - original_begin); } // Returns true if `v` is one of the chars allowed inside parentheses following @@ -372,7 +372,7 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end, int exponent_adjustment = 0; bool mantissa_is_inexact = false; - std::size_t pre_decimal_digits = ConsumeDigits( + int pre_decimal_digits = ConsumeDigits( begin, end, MantissaDigitsMax(), &mantissa, &mantissa_is_inexact); begin += pre_decimal_digits; int digits_left; @@ -398,14 +398,14 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end, while (begin < end && *begin == '0') { ++begin; } - std::size_t zeros_skipped = begin - begin_zeros; + int zeros_skipped = static_cast(begin - begin_zeros); if (zeros_skipped >= DigitLimit()) { // refuse to parse pathological inputs return result; } exponent_adjustment -= static_cast(zeros_skipped); } - int64_t post_decimal_digits = ConsumeDigits( + int post_decimal_digits = ConsumeDigits( begin, end, digits_left, &mantissa, &mantissa_is_inexact); begin += post_decimal_digits; diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc index 194e21af..4e68b90b 100644 --- a/absl/strings/internal/str_format/bind.cc +++ b/absl/strings/internal/str_format/bind.cc @@ -235,7 +235,7 @@ int FprintF(std::FILE* output, const UntypedFormatSpecImpl format, errno = sink.error(); return -1; } - if (sink.count() > std::numeric_limits::max()) { + if (sink.count() > static_cast(std::numeric_limits::max())) { errno = EFBIG; return -1; } diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index d3c5f0a7..0ded0a66 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -134,7 +134,7 @@ class BinaryToDecimal { assert(exp > 0); assert(exp <= std::numeric_limits::max_exponent); static_assert( - StackArray::kMaxCapacity >= + static_cast(StackArray::kMaxCapacity) >= ChunksNeeded(std::numeric_limits::max_exponent), ""); diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc index 19f9aab5..27fec216 100644 --- a/absl/synchronization/internal/graphcycles.cc +++ b/absl/synchronization/internal/graphcycles.cc @@ -37,6 +37,7 @@ #include #include +#include #include "absl/base/internal/hide_ptr.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh index b96fe890..afad301e 100644 --- a/ci/linux_docker_containers.sh +++ b/ci/linux_docker_containers.sh @@ -19,4 +19,3 @@ 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_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" diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-4.9_libstdcxx_bazel.sh deleted file mode 100755 index 16f927bd..00000000 --- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# -# Copyright 2019 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_49_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="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${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="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${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 \ - --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \ - --workdir=/abseil-cpp \ - --cap-add=SYS_PTRACE \ - --rm \ - -e CC="/usr/bin/gcc-4.9" \ - -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 -- cgit v1.2.3