From 029795a9b5281379f892fbbe3f9a400d5a33f5cc Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 10 Oct 2017 17:07:46 -0700 Subject: Changes imported from Abseil "staging" branch: - 3e05f2c346a9faf07088c49d590d49a9199e7edd Simplify Duration's operator-() by Jorg Brown - 3c4942375a6d17e887bb6ab7cf2d0e763d58a511 Rewrite `noexcept(noexcept(allocator_type()))` to instead... by Matt Calabrese - 02f35a684201a6aa9f70e8b0a041993676f2d230 Fix comment on remove_prefix since the function is not re... by Abseil Team - ceb40aba8031e0ccec9cd49da844882df100c56f Fix mutex_test under TSAN. by Derek Mauro - 7bd12e7ddc5d074e1b9c9f037879211fa1d81f8c Slight wording tweaks for "adopting" wrappers by Abseil Team - c3580afe092e0357d40b1769314f36da1b887c65 Internal cleanup. by Greg Miller GitOrigin-RevId: 3e05f2c346a9faf07088c49d590d49a9199e7edd Change-Id: If3df72fba3803398cfcbb323fb4cb84ec55511aa --- .ci/abseil-cpp.json | 8 --- absl/container/inlined_vector.h | 3 +- absl/memory/memory.h | 21 ++++---- absl/strings/string_view.h | 5 +- absl/synchronization/mutex_test.cc | 103 +++++++++++++++++++------------------ absl/time/internal/test_util.cc | 2 +- absl/time/time.h | 37 ++++++------- 7 files changed, 88 insertions(+), 91 deletions(-) delete mode 100644 .ci/abseil-cpp.json diff --git a/.ci/abseil-cpp.json b/.ci/abseil-cpp.json deleted file mode 100644 index a90cc17..0000000 --- a/.ci/abseil-cpp.json +++ /dev/null @@ -1,8 +0,0 @@ -// This is a relaxed JSON format, you can have comments in it. -// This is a list of configuration for the job that does not specify a configuration. -[ - {"node": "linux-x86_64"}, - {"node": "ubuntu_16.04-x86_64"}, - {"node": "darwin-x86_64"}, - {"node": "windows-x86_64"} -] diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index f68ca50..96a9d00 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; using const_reverse_iterator = std::reverse_iterator; - InlinedVector() noexcept(noexcept(allocator_type())) + InlinedVector() noexcept( + std::is_nothrow_default_constructible::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 c679960..9590913 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::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 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 951e9cb..c3acd72 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 cfe8109..5a5874d 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( - 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( - 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 1a415f8..8bb27a8 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(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(America_Los_Angeles), America_Los_Angeles_len}, diff --git a/absl/time/time.h b/absl/time/time.h index 093f168..c01977b 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -1126,8 +1126,10 @@ constexpr Duration OppositeInfinity(Duration d) { : MakeDuration(std::numeric_limits::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::min() && - time_internal::GetRepLo(d) == 0) + return time_internal::GetRepLo(d) == 0 + ? time_internal::GetRepHi(d) == std::numeric_limits::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) { -- cgit v1.2.3