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
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index 40cce04..1a3ca7c 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -38,12 +38,18 @@
     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 @@
   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 @@
   }
 }
 
+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 {
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index 91fcdb3..ee4d293 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -258,14 +258,23 @@
 // 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
diff --git a/absl/profiling/internal/sample_recorder.h b/absl/profiling/internal/sample_recorder.h
index 5e04a9c..6c14621 100644
--- a/absl/profiling/internal/sample_recorder.h
+++ b/absl/profiling/internal/sample_recorder.h
@@ -75,6 +75,7 @@
   // 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 @@
   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
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 4e37151..5d433cc 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -436,6 +436,7 @@
         "//absl/container:inlined_vector",
         "//absl/functional:function_ref",
         "//absl/meta:type_traits",
+        "//absl/numeric:bits",
         "//absl/types:optional",
         "//absl/types:span",
     ],
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index 662e889..27d3475 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -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 @@
   //
   // 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()
   //
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index 8a31179..ea865cc 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -49,6 +49,11 @@
 
 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 @@
 
 
 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, 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, 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;
 
diff --git a/absl/strings/internal/cord_rep_flat.h b/absl/strings/internal/cord_rep_flat.h
index a15c9ac..ae8b3a2 100644
--- a/absl/strings/internal/cord_rep_flat.h
+++ b/absl/strings/internal/cord_rep_flat.h
@@ -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 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) {
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index 31dbf67..d97d503 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -229,10 +229,11 @@
   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 @@
 
       // 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();
       }
     }
   }
diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc
index 2be6256..c986e86 100644
--- a/absl/strings/str_join_test.cc
+++ b/absl/strings/str_join_test.cc
@@ -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 @@
                           "-", 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