Export of internal Abseil changes

--
5ff0c4b38386ae80b25e9f8d0e1bac07fd7ce92c by Martijn Vels <mvels@google.com>:

Add CordzUpdateTracker class

PiperOrigin-RevId: 368469046

--
4de916b1ba4b5480b4dbe93d28c5eaa110449c66 by Derek Mauro <dmauro@google.com>:

Adds `ABSL_ATTRIBUTE_LIFETIME_BOUND` to `absl::Span`s initializer_list
constructor.

Compilers that support this attribute will emit a warning
if the parameter does not have sufficient lifetime.

For more information, see
https://github.com/abseil/abseil-cpp/blob/b97a1ecda869ca8754d467a56c50275cebfeb328/absl/types/span.h#L209-L248

PiperOrigin-RevId: 368429085

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

Reorganize internal cord code in CMakeLists.txt into cord_internal library

PiperOrigin-RevId: 368423765

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

Internal change

PiperOrigin-RevId: 368346725
GitOrigin-RevId: 5ff0c4b38386ae80b25e9f8d0e1bac07fd7ce92c
Change-Id: Ic4627eab4f0274e400a6d12cde3341fb538de075
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 253c73f..4527ca1 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -203,6 +203,7 @@
   "strings/internal/cord_rep_ring.cc"
   "strings/internal/cord_rep_ring.h"
   "strings/internal/cord_rep_ring_reader.h"
+  "strings/internal/cordz_update_tracker.h"
   "strings/internal/charconv_bigint.cc"
   "strings/internal/charconv_bigint.h"
   "strings/internal/charconv_parse.cc"
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 123b5ef..1138516 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -297,6 +297,26 @@
 )
 
 cc_library(
+    name = "cordz_update_tracker",
+    hdrs = ["internal/cordz_update_tracker.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+    deps = ["//absl/base:config"],
+)
+
+cc_test(
+    name = "cordz_update_tracker_test",
+    srcs = ["internal/cordz_update_tracker_test.cc"],
+    deps = [
+        ":cordz_update_tracker",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/synchronization",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "cord",
     srcs = [
         "cord.cc",
@@ -307,6 +327,7 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         ":cord_internal",
+        ":cordz_update_tracker",
         ":internal",
         ":str_format",
         ":strings",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 3b7ae63..0d93d5f 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -552,24 +552,71 @@
 
 absl_cc_library(
   NAME
+    cord_internal
+  HDRS
+    "internal/cord_internal.h"
+    "internal/cord_rep_flat.h"
+    "internal/cord_rep_ring.h"
+    "internal/cord_rep_ring_reader.h"
+  SRCS
+    "internal/cord_internal.cc"
+    "internal/cord_rep_ring.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base_internal
+    absl::compressed_tuple
+    absl::config
+    absl::core_headers
+    absl::endian
+    absl::inlined_vector
+    absl::layout
+    absl::raw_logging_internal
+    absl::strings
+    absl::throw_delegate
+    absl::type_traits
+)
+
+absl_cc_library(
+  NAME
+    cordz_update_tracker
+  HDRS
+    "internal/cordz_update_tracker.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+)
+
+absl_cc_test(
+  NAME
+    cordz_update_tracker_test
+  SRCS
+    "internal/cordz_update_tracker_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::cordz_update_tracker
+    absl::core_headers
+    absl::synchronization
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
     cord
   HDRS
     "cord.h"
   SRCS
     "cord.cc"
-    "internal/cord_internal.cc"
-    "internal/cord_internal.h"
-    "internal/cord_rep_ring.h"
-    "internal/cord_rep_ring.cc"
-    "internal/cord_rep_ring_reader.h"
-    "internal/cord_rep_flat.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::base
-    absl::base_internal
-    absl::compressed_tuple
     absl::config
+    absl::cord_internal
+    absl::cordz_update_tracker
     absl::core_headers
     absl::endian
     absl::fixed_array
@@ -578,8 +625,6 @@
     absl::optional
     absl::raw_logging_internal
     absl::strings
-    absl::strings_internal
-    absl::throw_delegate
     absl::type_traits
   PUBLIC
 )
@@ -624,12 +669,12 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
-    absl::config
-    absl::cord
-    absl::strings
     absl::base
+    absl::config
+    absl::cord_internal
     absl::core_headers
     absl::raw_logging_internal
+    absl::strings
     gmock_main
 )
 
@@ -641,9 +686,9 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
-    absl::cord
-    absl::strings
     absl::base
+    absl::cord_internal
     absl::core_headers
+    absl::strings
     gmock_main
 )
diff --git a/absl/strings/internal/cordz_update_tracker.h b/absl/strings/internal/cordz_update_tracker.h
new file mode 100644
index 0000000..3c617e9
--- /dev/null
+++ b/absl/strings/internal/cordz_update_tracker.h
@@ -0,0 +1,96 @@
+// Copyright 2021 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.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
+#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// CordzUpdateTracker tracks counters for Cord update methods.
+//
+// The purpose of CordzUpdateTracker is to track the number of calls to methods
+// updating Cord data for sampled cords. The class internally uses 'lossy'
+// atomic operations: Cord is thread-compatible, so there is no need to
+// synchronize updates. However, Cordz collection threads may call 'Value()' at
+// any point, so the class needs to provide thread safe access.
+//
+// This class is thread-safe. But as per above comments, all non-const methods
+// should be used single-threaded only: updates are thread-safe but lossy.
+class CordzUpdateTracker {
+ public:
+  // Tracked update methods.
+  enum MethodIdentifier {
+    kAssignString,
+    kAssignCord,
+    kMoveAssignCord,
+    kAppendString,
+    kAppendCord,
+    kMoveAppendCord,
+    kPrependString,
+    kPrependCord,
+    kMovePrependCord,
+    kAppendExternalMemory,
+    kFlatten,
+    kGetAppendRegion,
+    kRemovePrefix,
+    kRemoveSuffic,
+    kSubCord,
+
+    // kNumMethods defines the number of entries: must be the last entry.
+    kNumMethods,
+  };
+
+  // Constructs a new instance. All counters are zero-initialized.
+  constexpr CordzUpdateTracker() noexcept : values_{} {}
+
+  // Copy constructs a new instance.
+  CordzUpdateTracker(const CordzUpdateTracker& rhs) noexcept { *this = rhs; }
+
+  // Assigns the provided value to this instance.
+  CordzUpdateTracker& operator=(const CordzUpdateTracker& rhs) noexcept {
+    for (int i = 0; i < kNumMethods; ++i) {
+      values_[i].store(rhs.values_[i].load(std::memory_order_relaxed),
+                       std::memory_order_relaxed);
+    }
+    return *this;
+  }
+
+  // Returns the value for the specified method.
+  int64_t Value(MethodIdentifier method) const {
+    return values_[method].load(std::memory_order_relaxed);
+  }
+
+  // Increases the value for the specified method by `n`
+  void LossyAdd(MethodIdentifier method, int64_t n = 1) {
+    auto& value = values_[method];
+    value.store(value.load(std::memory_order_relaxed) + n,
+                std::memory_order_relaxed);
+  }
+
+ private:
+  std::atomic<int64_t> values_[kNumMethods];
+};
+
+}  // namespace cord_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
diff --git a/absl/strings/internal/cordz_update_tracker_test.cc b/absl/strings/internal/cordz_update_tracker_test.cc
new file mode 100644
index 0000000..4578204
--- /dev/null
+++ b/absl/strings/internal/cordz_update_tracker_test.cc
@@ -0,0 +1,130 @@
+// Copyright 2021 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.
+
+#include "absl/strings/internal/cordz_update_tracker.h"
+
+#include <array>
+#include <thread>  // NOLINT
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/synchronization/notification.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+namespace {
+
+using ::testing::AnyOf;
+using ::testing::Eq;
+
+using Method = CordzUpdateTracker::MethodIdentifier;
+using Methods = std::array<Method, Method::kNumMethods>;
+
+// Returns an array of all methods defined in `MethodIdentifier`
+Methods AllMethods() {
+  return Methods{Method::kAssignString,    Method::kAssignCord,
+                 Method::kMoveAssignCord,  Method::kAppendString,
+                 Method::kAppendCord,      Method::kMoveAppendCord,
+                 Method::kPrependString,   Method::kPrependCord,
+                 Method::kMovePrependCord, Method::kAppendExternalMemory,
+                 Method::kFlatten,         Method::kGetAppendRegion,
+                 Method::kRemovePrefix,    Method::kRemoveSuffic,
+                 Method::kSubCord};
+}
+
+TEST(CordzUpdateTracker, IsConstExprAndInitializesToZero) {
+  constexpr CordzUpdateTracker tracker;
+  for (Method method : AllMethods()) {
+    ASSERT_THAT(tracker.Value(method), Eq(0));
+  }
+}
+
+TEST(CordzUpdateTracker, LossyAdd) {
+  int64_t n = 1;
+  CordzUpdateTracker tracker;
+  for (Method method : AllMethods()) {
+    tracker.LossyAdd(method, n);
+    EXPECT_THAT(tracker.Value(method), Eq(n));
+    n += 2;
+  }
+}
+
+TEST(CordzUpdateTracker, CopyConstructor) {
+  int64_t n = 1;
+  CordzUpdateTracker src;
+  for (Method method : AllMethods()) {
+    src.LossyAdd(method, n);
+    n += 2;
+  }
+
+  n = 1;
+  CordzUpdateTracker tracker(src);
+  for (Method method : AllMethods()) {
+    EXPECT_THAT(tracker.Value(method), Eq(n));
+    n += 2;
+  }
+}
+
+TEST(CordzUpdateTracker, OperatorAssign) {
+  int64_t n = 1;
+  CordzUpdateTracker src;
+  CordzUpdateTracker tracker;
+  for (Method method : AllMethods()) {
+    src.LossyAdd(method, n);
+    n += 2;
+  }
+
+  n = 1;
+  tracker = src;
+  for (Method method : AllMethods()) {
+    EXPECT_THAT(tracker.Value(method), Eq(n));
+    n += 2;
+  }
+}
+
+TEST(CordzUpdateTracker, ThreadSanitizedValueCheck) {
+  absl::Notification done;
+  CordzUpdateTracker tracker;
+
+  std::thread reader([&done, &tracker] {
+    while (!done.HasBeenNotified()) {
+      int n = 1;
+      for (Method method : AllMethods()) {
+        EXPECT_THAT(tracker.Value(method), AnyOf(Eq(n), Eq(0)));
+        n += 2;
+      }
+    }
+    int n = 1;
+    for (Method method : AllMethods()) {
+      EXPECT_THAT(tracker.Value(method), Eq(n));
+      n += 2;
+    }
+  });
+
+  int64_t n = 1;
+  for (Method method : AllMethods()) {
+    tracker.LossyAdd(method, n);
+    n += 2;
+  }
+  done.Notify();
+  reader.join();
+}
+
+}  // namespace
+}  // namespace cord_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/types/span.h b/absl/types/span.h
index 95fe792..41db342 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -243,8 +243,8 @@
   //
   template <typename LazyT = T,
             typename = EnableIfConstView<LazyT>>
-  Span(
-      std::initializer_list<value_type> v) noexcept  // NOLINT(runtime/explicit)
+  Span(std::initializer_list<value_type> v
+           ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/explicit)
       : Span(v.begin(), v.size()) {}
 
   // Accessors