about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.ci/abseil-cpp.json3
-rw-r--r--absl/container/inlined_vector.h3
-rw-r--r--absl/memory/memory.h21
-rw-r--r--absl/strings/string_view.h5
-rw-r--r--absl/synchronization/mutex_test.cc103
-rw-r--r--absl/time/internal/test_util.cc2
-rw-r--r--absl/time/time.h37
7 files changed, 89 insertions, 85 deletions
diff --git a/.ci/abseil-cpp.json b/.ci/abseil-cpp.json
index a90cc1717e54..b21e68d1c230 100644
--- a/.ci/abseil-cpp.json
+++ b/.ci/abseil-cpp.json
@@ -3,6 +3,5 @@
 [
     {"node": "linux-x86_64"},
     {"node": "ubuntu_16.04-x86_64"},
-    {"node": "darwin-x86_64"},
-    {"node": "windows-x86_64"}
+    {"node": "darwin-x86_64"}
 ]
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index f68ca5074149..96a9d001a355 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -82,7 +82,8 @@ class InlinedVector {
   using reverse_iterator = std::reverse_iterator<iterator>;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
 
-  InlinedVector() noexcept(noexcept(allocator_type()))
+  InlinedVector() noexcept(
+      std::is_nothrow_default_constructible<allocator_type>::value)
       : allocator_and_tag_(allocator_type()) {}
 
   explicit InlinedVector(const allocator_type& alloc) noexcept
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index c67996084ef6..959091388243 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -38,8 +38,8 @@ namespace absl {
 // Function Template: WrapUnique()
 // -----------------------------------------------------------------------------
 //
-// Transfers ownership of a raw pointer to a `std::unique_ptr`. The returned
-// value is a `std::unique_ptr` of deduced type.
+//  Adopts ownership from a raw pointer and transfers it to the returned
+//  `std::unique_ptr`, whose type is deduced.
 //
 // Example:
 //   X* NewX(int, int);
@@ -169,8 +169,8 @@ typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
 // Function Template: RawPtr()
 // -----------------------------------------------------------------------------
 //
-// Extracts the raw pointer from a pointer-like 'ptr'. `absl::RawPtr` is useful
-// within templates that need to handle a complement of raw pointers,
+// Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is
+// useful within templates that need to handle a complement of raw pointers,
 // `std::nullptr_t`, and smart pointers.
 template <typename T>
 auto RawPtr(T&& ptr) -> decltype(&*ptr) {
@@ -183,9 +183,9 @@ inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
 // Function Template: ShareUniquePtr()
 // -----------------------------------------------------------------------------
 //
-// Transforms a `std::unique_ptr` rvalue into a `std::shared_ptr`. The returned
-// value is a `std::shared_ptr` of deduced type and ownership is transferred to
-// the shared pointer.
+// Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced
+// type. Ownership (if any) of the held value is transferred to the returned
+// shared pointer.
 //
 // Example:
 //
@@ -194,8 +194,11 @@ inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
 //     CHECK_EQ(*sp, 10);
 //     CHECK(up == nullptr);
 //
-// Note that this conversion is correct even when T is an array type, although
-// the resulting shared pointer may not be very useful.
+// Note that this conversion is correct even when T is an array type, and more
+// generally it works for *any* deleter of the `unique_ptr` (single-object
+// deleter, array deleter, or any custom deleter), since the deleter is adopted
+// by the shared pointer as well. The deleter is copied (unless it is a
+// reference).
 //
 // Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a
 // null shared pointer does not attempt to call the deleter.
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 951e9cbc039c..c3acd7290993 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -295,9 +295,8 @@ class string_view {
 
   // string_view::remove_prefix()
   //
-  // Removes the first `n` characters from the `string_view`, returning a
-  // pointer to the new first character. Note that the underlying std::string is not
-  // changed, only the view.
+  // Removes the first `n` characters from the `string_view`. Note that the
+  // underlying std::string is not changed, only the view.
   void remove_prefix(size_type n) {
     assert(n <= length_);
     ptr_ += n;
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index cfe81096dc98..5a5874def72d 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -89,8 +89,6 @@ static void CheckSumG0G1(void *v) {
 }
 
 static void TestMu(TestContext *cxt, int c) {
-  SetInvariantChecked(false);
-  cxt->mu.EnableInvariantDebugging(CheckSumG0G1, cxt);
   for (int i = 0; i != cxt->iterations; i++) {
     absl::MutexLock l(&cxt->mu);
     int a = cxt->g0 + 1;
@@ -100,8 +98,6 @@ static void TestMu(TestContext *cxt, int c) {
 }
 
 static void TestTry(TestContext *cxt, int c) {
-  SetInvariantChecked(false);
-  cxt->mu.EnableInvariantDebugging(CheckSumG0G1, cxt);
   for (int i = 0; i != cxt->iterations; i++) {
     do {
       std::this_thread::yield();
@@ -122,8 +118,6 @@ static void TestR20ms(TestContext *cxt, int c) {
 }
 
 static void TestRW(TestContext *cxt, int c) {
-  SetInvariantChecked(false);
-  cxt->mu.EnableInvariantDebugging(CheckSumG0G1, cxt);
   if ((c & 1) == 0) {
     for (int i = 0; i != cxt->iterations; i++) {
       absl::WriterMutexLock l(&cxt->mu);
@@ -356,67 +350,57 @@ static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
   cv->Signal();
 }
 
-// Basis for the parameterized tests configured below.
-static int RunTest(void (*test)(TestContext *cxt, int), int threads,
-                   int iterations, int operations) {
-  TestContext cxt;
+// Code common to RunTest() and RunTestWithInvariantDebugging().
+static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
+                         int threads, int iterations, int operations) {
   absl::Mutex mu2;
   absl::CondVar cv2;
-  int c0;
-  int c1;
-
-  // run with large thread count for full test and to get timing
-
-#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
-  absl::EnableMutexInvariantDebugging(false);
-#endif
-  c0 = 0;
-  c1 = 0;
-  cxt.g0 = 0;
-  cxt.g1 = 0;
-  cxt.iterations = iterations;
-  cxt.threads = threads;
+  int c0 = 0;
+  int c1 = 0;
+  cxt->g0 = 0;
+  cxt->g1 = 0;
+  cxt->iterations = iterations;
+  cxt->threads = threads;
   absl::synchronization_internal::ThreadPool tp(threads);
   for (int i = 0; i != threads; i++) {
     tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2,
                           std::function<void(int)>(
-                              std::bind(test, &cxt, std::placeholders::_1))));
+                              std::bind(test, cxt, std::placeholders::_1))));
   }
   mu2.Lock();
   while (c1 != threads) {
     cv2.Wait(&mu2);
   }
   mu2.Unlock();
-  int saved_g0 = cxt.g0;
+  return cxt->g0;
+}
 
-  // run again with small number of iterations to test invariant checking
+// Basis for the parameterized tests configured below.
+static int RunTest(void (*test)(TestContext *cxt, int), int threads,
+                   int iterations, int operations) {
+  TestContext cxt;
+  return RunTestCommon(&cxt, test, threads, iterations, operations);
+}
 
+// Like RunTest(), but sets an invariant on the tested Mutex and
+// verifies that the invariant check happened. The invariant function
+// will be passed the TestContext* as its arg and must call
+// SetInvariantChecked(true);
 #if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
+static int RunTestWithInvariantDebugging(void (*test)(TestContext *cxt, int),
+                                         int threads, int iterations,
+                                         int operations,
+                                         void (*invariant)(void *)) {
   absl::EnableMutexInvariantDebugging(true);
-#endif
-  SetInvariantChecked(true);
-  c0 = 0;
-  c1 = 0;
-  cxt.g0 = 0;
-  cxt.g1 = 0;
-  cxt.iterations = (iterations > 10 ? 10 : iterations);
-  cxt.threads = threads;
-  for (int i = 0; i != threads; i++) {
-    tp.Schedule(std::bind(&EndTest, &c0, &c1, &mu2, &cv2,
-                          std::function<void(int)>(
-                              std::bind(test, &cxt, std::placeholders::_1))));
-  }
-  mu2.Lock();
-  while (c1 != threads) {
-    cv2.Wait(&mu2);
-  }
-  mu2.Unlock();
-#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
+  SetInvariantChecked(false);
+  TestContext cxt;
+  cxt.mu.EnableInvariantDebugging(invariant, &cxt);
+  int ret = RunTestCommon(&cxt, test, threads, iterations, operations);
   ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
-#endif
-
-  return saved_g0;
+  absl::EnableMutexInvariantDebugging(false);  // Restore.
+  return ret;
 }
+#endif
 
 // --------------------------------------------------------
 // Test for fix of bug in TryRemove()
@@ -1463,6 +1447,13 @@ TEST_P(MutexVariableThreadCountTest, Mutex) {
   int iterations = ScaleIterations(10000000) / threads;
   int operations = threads * iterations;
   EXPECT_EQ(RunTest(&TestMu, threads, iterations, operations), operations);
+#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
+  iterations = std::min(iterations, 10);
+  operations = threads * iterations;
+  EXPECT_EQ(RunTestWithInvariantDebugging(&TestMu, threads, iterations,
+                                          operations, CheckSumG0G1),
+            operations);
+#endif
 }
 
 TEST_P(MutexVariableThreadCountTest, Try) {
@@ -1470,6 +1461,13 @@ TEST_P(MutexVariableThreadCountTest, Try) {
   int iterations = 1000000 / threads;
   int operations = iterations * threads;
   EXPECT_EQ(RunTest(&TestTry, threads, iterations, operations), operations);
+#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
+  iterations = std::min(iterations, 10);
+  operations = threads * iterations;
+  EXPECT_EQ(RunTestWithInvariantDebugging(&TestTry, threads, iterations,
+                                          operations, CheckSumG0G1),
+            operations);
+#endif
 }
 
 TEST_P(MutexVariableThreadCountTest, R20ms) {
@@ -1484,6 +1482,13 @@ TEST_P(MutexVariableThreadCountTest, RW) {
   int iterations = ScaleIterations(20000000) / threads;
   int operations = iterations * threads;
   EXPECT_EQ(RunTest(&TestRW, threads, iterations, operations), operations / 2);
+#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
+  iterations = std::min(iterations, 10);
+  operations = threads * iterations;
+  EXPECT_EQ(RunTestWithInvariantDebugging(&TestRW, threads, iterations,
+                                          operations, CheckSumG0G1),
+            operations / 2);
+#endif
 }
 
 TEST_P(MutexVariableThreadCountTest, Await) {
diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc
index 1a415f89469e..8bb27a8f3ef2 100644
--- a/absl/time/internal/test_util.cc
+++ b/absl/time/internal/test_util.cc
@@ -63,7 +63,7 @@ const struct ZoneInfo {
     {"US/Pacific",  //
      reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len},
 
-    // Allows use of the local time zone from a common system-specific location.
+    // Allows use of the local time zone from a system-specific location.
 #ifdef _MSC_VER
     {"localtime",  //
      reinterpret_cast<char*>(America_Los_Angeles), America_Los_Angeles_len},
diff --git a/absl/time/time.h b/absl/time/time.h
index 093f168df449..c01977b003eb 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -1126,8 +1126,10 @@ constexpr Duration OppositeInfinity(Duration d) {
              : MakeDuration(std::numeric_limits<int64_t>::min(), ~0U);
 }
 
-// Returns (-n)-1 (equivalently -(n+1)) without overflowing on any input value.
+// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.
 constexpr int64_t NegateAndSubtractOne(int64_t n) {
+  // Note: Good compilers will optimize this expression to ~n when using
+  // a two's-complement representation (which is required for int64_t).
   return (n < 0) ? -(n + 1) : (-n) - 1;
 }
 
@@ -1232,31 +1234,26 @@ constexpr bool operator==(Duration lhs, Duration rhs) {
 constexpr Duration operator-(Duration d) {
   // This is a little interesting because of the special cases.
   //
-  // Infinities stay infinite, and just change direction.
+  // If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're
+  // dealing with an integral number of seconds, and the only special case is
+  // the maximum negative finite duration, which can't be negated.
   //
-  // The maximum negative finite duration can't be negated (at least, not
-  // on a two's complement machine), so we return infinity for that case.
-  // Next we dispatch the case where rep_lo_ is zero, observing that it's
-  // safe to negate rep_hi_ in this case because it's not int64_t-min (or
-  // else we'd have handled it above, returning InfiniteDuration()).
+  // Infinities stay infinite, and just change direction.
   //
   // Finally we're in the case where rep_lo_ is non-zero, and we can borrow
   // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1
   // is safe).
-  return time_internal::IsInfiniteDuration(d)
-             ? time_internal::OppositeInfinity(d)
-             : (time_internal::GetRepHi(d) ==
-                    std::numeric_limits<int64_t>::min() &&
-                time_internal::GetRepLo(d) == 0)
+  return time_internal::GetRepLo(d) == 0
+             ? time_internal::GetRepHi(d) == std::numeric_limits<int64_t>::min()
                    ? InfiniteDuration()
-                   : (time_internal::GetRepLo(d) == 0)
-                         ? time_internal::MakeDuration(
-                               -time_internal::GetRepHi(d))
-                         : time_internal::MakeDuration(
-                               time_internal::NegateAndSubtractOne(
-                                   time_internal::GetRepHi(d)),
-                               time_internal::kTicksPerSecond -
-                                   time_internal::GetRepLo(d));
+                   : time_internal::MakeDuration(-time_internal::GetRepHi(d))
+             : time_internal::IsInfiniteDuration(d)
+                   ? time_internal::OppositeInfinity(d)
+                   : time_internal::MakeDuration(
+                         time_internal::NegateAndSubtractOne(
+                             time_internal::GetRepHi(d)),
+                         time_internal::kTicksPerSecond -
+                             time_internal::GetRepLo(d));
 }
 
 constexpr Duration Nanoseconds(int64_t n) {