Export of internal Abseil changes

--
a9ea60e9c0ccd744b6f12fd021dbedfe826dfe84 by Matt Kulukundis <kfm@google.com>:

Add an internal hook to allow keeping flags in sync with global state.

Rollforward, except continue including hashtablez_flags.h in absl_flags.h so users don't break.

PiperOrigin-RevId: 412198044

--
183e5c440b68c797ce4a82102f94f41c97a14674 by Martijn Vels <mvels@google.com>:

Internal cleanups and changes

PiperOrigin-RevId: 412083793

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

Mark Cord::Clear() with the ABSL_ATTRIBUTE_REINITIALIZES attribute.

This prevents false positives in the clang-tidy check bugprone-use-after-move; it allows Clear() to be called on a moved-from Cord without any warnings, and the Cord will thereafter be regarded as initialized again.

PiperOrigin-RevId: 412082757

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

StrJoin: Support iterators that do not have an `operator->`

Allows using `StrJoin` with iterators that do not have an `operator->`.
The `operator->` requirement for input iterators was dropped in C++20.

PiperOrigin-RevId: 412066130

--
6773c0ced2caa6a7855898298faecc584f3997ec by Andy Soffer <asoffer@google.com>:

Rollback of internal hook for keeping flags in sync with global state.

PiperOrigin-RevId: 411895027

--
4e7016a2fb88ce97853ef85ad5b4f76998eacca1 by Matt Kulukundis <kfm@google.com>:

Add an internal hook to allow keeping flags in sync with global state.

PiperOrigin-RevId: 411867376

--
2a7d4056e467b6b5d8a7aa9398d6cb5454c10fc5 by Martijn Vels <mvels@google.com>:

Internal change

PiperOrigin-RevId: 411806932
GitOrigin-RevId: a9ea60e9c0ccd744b6f12fd021dbedfe826dfe84
Change-Id: Ib35bb7b40774979ed2ad205bbb1744b1085eae78
pull/1074/head
Abseil Team 3 years ago committed by Andy Getz
parent ec0d76f1d0
commit 3e1983c5c0
  1. 37
      absl/container/internal/hashtablez_sampler.cc
  2. 9
      absl/container/internal/hashtablez_sampler.h
  3. 6
      absl/profiling/internal/sample_recorder.h
  4. 1
      absl/strings/BUILD.bazel
  5. 3
      absl/strings/cord.h
  6. 26
      absl/strings/cord_test.cc
  7. 6
      absl/strings/internal/cord_rep_flat.h
  8. 15
      absl/strings/internal/str_join_internal.h
  9. 134
      absl/strings/str_join_test.cc

@ -38,12 +38,18 @@ ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
false
};
ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
std::atomic<HashtablezConfigListener> g_hashtablez_config_listener{nullptr};
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
ABSL_PER_THREAD_TLS_KEYWORD absl::profiling_internal::ExponentialBiased
g_exponential_biased_generator;
#endif
void TriggerHashtablezConfigListener() {
auto* listener = g_hashtablez_config_listener.load(std::memory_order_acquire);
if (listener != nullptr) listener();
}
} // namespace
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
@ -163,11 +169,33 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
info->size.fetch_add(1, std::memory_order_relaxed);
}
void SetHashtablezConfigListener(HashtablezConfigListener l) {
g_hashtablez_config_listener.store(l, std::memory_order_release);
}
bool IsHashtablezEnabled() {
return g_hashtablez_enabled.load(std::memory_order_acquire);
}
void SetHashtablezEnabled(bool enabled) {
SetHashtablezEnabledInternal(enabled);
TriggerHashtablezConfigListener();
}
void SetHashtablezEnabledInternal(bool enabled) {
g_hashtablez_enabled.store(enabled, std::memory_order_release);
}
int32_t GetHashtablezSampleParameter() {
return g_hashtablez_sample_parameter.load(std::memory_order_acquire);
}
void SetHashtablezSampleParameter(int32_t rate) {
SetHashtablezSampleParameterInternal(rate);
TriggerHashtablezConfigListener();
}
void SetHashtablezSampleParameterInternal(int32_t rate) {
if (rate > 0) {
g_hashtablez_sample_parameter.store(rate, std::memory_order_release);
} else {
@ -176,7 +204,16 @@ void SetHashtablezSampleParameter(int32_t rate) {
}
}
int32_t GetHashtablezMaxSamples() {
return GlobalHashtablezSampler().GetMaxSamples();
}
void SetHashtablezMaxSamples(int32_t max) {
SetHashtablezMaxSamplesInternal(max);
TriggerHashtablezConfigListener();
}
void SetHashtablezMaxSamplesInternal(int32_t max) {
if (max > 0) {
GlobalHashtablezSampler().SetMaxSamples(max);
} else {

@ -258,14 +258,23 @@ using HashtablezSampler =
// Returns a global Sampler.
HashtablezSampler& GlobalHashtablezSampler();
using HashtablezConfigListener = void (*)();
void SetHashtablezConfigListener(HashtablezConfigListener l);
// Enables or disables sampling for Swiss tables.
bool IsHashtablezEnabled();
void SetHashtablezEnabled(bool enabled);
void SetHashtablezEnabledInternal(bool enabled);
// Sets the rate at which Swiss tables will be sampled.
int32_t GetHashtablezSampleParameter();
void SetHashtablezSampleParameter(int32_t rate);
void SetHashtablezSampleParameterInternal(int32_t rate);
// Sets a soft max for the number of samples that will be kept.
int32_t GetHashtablezMaxSamples();
void SetHashtablezMaxSamples(int32_t max);
void SetHashtablezMaxSamplesInternal(int32_t max);
// Configuration override.
// This allows process-wide sampling without depending on order of

@ -75,6 +75,7 @@ class SampleRecorder {
// samples that have been dropped.
int64_t Iterate(const std::function<void(const T& stack)>& f);
int32_t GetMaxSamples() const;
void SetMaxSamples(int32_t max);
private:
@ -223,6 +224,11 @@ void SampleRecorder<T>::SetMaxSamples(int32_t max) {
max_samples_.store(max, std::memory_order_release);
}
template <typename T>
int32_t SampleRecorder<T>::GetMaxSamples() const {
return max_samples_.load(std::memory_order_acquire);
}
} // namespace profiling_internal
ABSL_NAMESPACE_END
} // namespace absl

@ -436,6 +436,7 @@ cc_library(
"//absl/container:inlined_vector",
"//absl/functional:function_ref",
"//absl/meta:type_traits",
"//absl/numeric:bits",
"//absl/types:optional",
"//absl/types:span",
],

@ -70,6 +70,7 @@
#include <string>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/per_thread_tls.h"
@ -215,7 +216,7 @@ class Cord {
//
// Releases the Cord data. Any nodes that share data with other Cords, if
// applicable, will have their reference counts reduced by 1.
void Clear();
ABSL_ATTRIBUTE_REINITIALIZES void Clear();
// Cord::Append()
//

@ -49,6 +49,11 @@ static constexpr auto MAX_FLAT_TAG = absl::cord_internal::MAX_FLAT_TAG;
typedef std::mt19937_64 RandomEngine;
using absl::cord_internal::CordRep;
using absl::cord_internal::CordRepFlat;
using absl::cord_internal::kFlatOverhead;
using absl::cord_internal::kMaxFlatLength;
static std::string RandomLowercaseString(RandomEngine* rng);
static std::string RandomLowercaseString(RandomEngine* rng, size_t length);
@ -266,10 +271,6 @@ INSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Values(0, 1, 2, 3),
TEST(CordRepFlat, AllFlatCapacities) {
using absl::cord_internal::CordRep;
using absl::cord_internal::CordRepFlat;
using absl::cord_internal::kFlatOverhead;
// Explicitly and redundantly assert built-in min/max limits
static_assert(absl::cord_internal::kFlatOverhead < 32, "");
static_assert(absl::cord_internal::kMinFlatSize == 32, "");
@ -310,9 +311,6 @@ TEST(CordRepFlat, AllFlatCapacities) {
}
TEST(CordRepFlat, MaxFlatSize) {
using absl::cord_internal::CordRep;
using absl::cord_internal::CordRepFlat;
using absl::cord_internal::kMaxFlatLength;
CordRepFlat* flat = CordRepFlat::New(kMaxFlatLength);
EXPECT_EQ(flat->Capacity(), kMaxFlatLength);
CordRep::Unref(flat);
@ -323,15 +321,23 @@ TEST(CordRepFlat, MaxFlatSize) {
}
TEST(CordRepFlat, MaxLargeFlatSize) {
using absl::cord_internal::CordRep;
using absl::cord_internal::CordRepFlat;
using absl::cord_internal::kFlatOverhead;
const size_t size = 256 * 1024 - kFlatOverhead;
CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), size);
EXPECT_GE(flat->Capacity(), size);
CordRep::Unref(flat);
}
TEST(CordRepFlat, AllFlatSizes) {
const size_t kMaxSize = 256 * 1024;
for (size_t size = 32; size <= kMaxSize; size *=2) {
const size_t length = size - kFlatOverhead - 1;
CordRepFlat* flat = CordRepFlat::New(CordRepFlat::Large(), length);
EXPECT_GE(flat->Capacity(), length);
memset(flat->Data(), 0xCD, flat->Capacity());
CordRep::Unref(flat);
}
}
TEST_P(CordTest, AllFlatSizes) {
using absl::strings_internal::CordTestAccess;

@ -20,6 +20,8 @@
#include <cstdint>
#include <memory>
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/strings/internal/cord_internal.h"
namespace absl {
@ -105,8 +107,8 @@ struct CordRepFlat : public CordRep {
struct Large {};
// Creates a new flat node.
template <size_t max_flat_size>
static CordRepFlat* NewImpl(size_t len) {
template <size_t max_flat_size, typename... Args>
static CordRepFlat* NewImpl(size_t len, Args... args ABSL_ATTRIBUTE_UNUSED) {
if (len <= kMinFlatLength) {
len = kMinFlatLength;
} else if (len > max_flat_size - kFlatOverhead) {

@ -229,10 +229,11 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
std::string result;
if (start != end) {
// Sums size
size_t result_size = start->size();
auto&& start_value = *start;
size_t result_size = start_value.size();
for (Iterator it = start; ++it != end;) {
result_size += s.size();
result_size += it->size();
result_size += (*it).size();
}
if (result_size > 0) {
@ -240,13 +241,15 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
// Joins strings
char* result_buf = &*result.begin();
memcpy(result_buf, start->data(), start->size());
result_buf += start->size();
memcpy(result_buf, start_value.data(), start_value.size());
result_buf += start_value.size();
for (Iterator it = start; ++it != end;) {
memcpy(result_buf, s.data(), s.size());
result_buf += s.size();
memcpy(result_buf, it->data(), it->size());
result_buf += it->size();
auto&& value = *it;
memcpy(result_buf, value.data(), value.size());
result_buf += value.size();
}
}
}

@ -21,6 +21,7 @@
#include <cstdio>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <map>
#include <memory>
#include <ostream>
@ -33,6 +34,7 @@
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
namespace {
@ -471,4 +473,136 @@ TEST(StrJoin, Tuple) {
"-", absl::DereferenceFormatter(TestFormatter())));
}
// A minimal value type for `StrJoin` inputs.
// Used to ensure we do not excessively require more a specific type, such as a
// `string_view`.
//
// Anything that can be `data()` and `size()` is OK.
class TestValue {
public:
TestValue(const char* data, size_t size) : data_(data), size_(size) {}
const char* data() const { return data_; }
size_t size() const { return size_; }
private:
const char* data_;
size_t size_;
};
// A minimal C++20 forward iterator, used to test that we do not impose
// excessive requirements on StrJoin inputs.
//
// The 2 main differences between pre-C++20 LegacyForwardIterator and the
// C++20 ForwardIterator are:
// 1. `operator->` is not required in C++20.
// 2. `operator*` result does not need to be an lvalue (a reference).
//
// The `operator->` requirement was removed on page 17 in:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1037r0.pdf
//
// See the `[iterator.requirements]` section of the C++ standard.
//
// The value type is a template parameter so that we can test the behaviour
// of `StrJoin` specializations, e.g. the NoFormatter specialization for
// `string_view`.
template <typename ValueT>
class TestIterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = ValueT;
using pointer = void;
using reference = const value_type&;
using difference_type = int;
// `data` must outlive the result.
static TestIterator begin(const std::vector<absl::string_view>& data) {
return TestIterator(&data, 0);
}
static TestIterator end(const std::vector<absl::string_view>& data) {
return TestIterator(nullptr, data.size());
}
bool operator==(const TestIterator& other) const {
return pos_ == other.pos_;
}
bool operator!=(const TestIterator& other) const {
return pos_ != other.pos_;
}
// This deliberately returns a `prvalue`.
// The requirement to return a reference was removed in C++20.
value_type operator*() const {
return ValueT((*data_)[pos_].data(), (*data_)[pos_].size());
}
// `operator->()` is deliberately omitted.
// The requirement to provide it was removed in C++20.
TestIterator& operator++() {
++pos_;
return *this;
}
TestIterator operator++(int) {
TestIterator result = *this;
++(*this);
return result;
}
TestIterator& operator--() {
--pos_;
return *this;
}
TestIterator operator--(int) {
TestIterator result = *this;
--(*this);
return result;
}
private:
TestIterator(const std::vector<absl::string_view>* data, size_t pos)
: data_(data), pos_(pos) {}
const std::vector<absl::string_view>* data_;
size_t pos_;
};
template <typename ValueT>
class TestIteratorRange {
public:
// `data` must be non-null and must outlive the result.
explicit TestIteratorRange(const std::vector<absl::string_view>& data)
: begin_(TestIterator<ValueT>::begin(data)),
end_(TestIterator<ValueT>::end(data)) {}
const TestIterator<ValueT>& begin() const { return begin_; }
const TestIterator<ValueT>& end() const { return end_; }
private:
TestIterator<ValueT> begin_;
TestIterator<ValueT> end_;
};
TEST(StrJoin, TestIteratorRequirementsNoFormatter) {
const std::vector<absl::string_view> a = {"a", "b", "c"};
// When the value type is string-like (`std::string` or `string_view`),
// the NoFormatter template specialization is used internally.
EXPECT_EQ("a-b-c",
absl::StrJoin(TestIteratorRange<absl::string_view>(a), "-"));
}
TEST(StrJoin, TestIteratorRequirementsCustomFormatter) {
const std::vector<absl::string_view> a = {"a", "b", "c"};
EXPECT_EQ("a-b-c",
absl::StrJoin(TestIteratorRange<TestValue>(a), "-",
[](std::string* out, const TestValue& value) {
absl::StrAppend(
out,
absl::string_view(value.data(), value.size()));
}));
}
} // namespace

Loading…
Cancel
Save