Changes imported from Abseil "staging" branch:
- 3e05f2c346a9faf07088c49d590d49a9199e7edd Simplify Duration's operator-() by Jorg Brown <jorg@google.com> - 3c4942375a6d17e887bb6ab7cf2d0e763d58a511 Rewrite `noexcept(noexcept(allocator_type()))` to instead... by Matt Calabrese <calabrese@google.com> - 02f35a684201a6aa9f70e8b0a041993676f2d230 Fix comment on remove_prefix since the function is not re... by Abseil Team <absl-team@google.com> - ceb40aba8031e0ccec9cd49da844882df100c56f Fix mutex_test under TSAN. by Derek Mauro <dmauro@google.com> - 7bd12e7ddc5d074e1b9c9f037879211fa1d81f8c Slight wording tweaks for "adopting" wrappers by Abseil Team <absl-team@google.com> - c3580afe092e0357d40b1769314f36da1b887c65 Internal cleanup. by Greg Miller <jgm@google.com> GitOrigin-RevId: 3e05f2c346a9faf07088c49d590d49a9199e7edd Change-Id: If3df72fba3803398cfcbb323fb4cb84ec55511aa
This commit is contained in:
parent
962e9931d5
commit
029795a9b5
7 changed files with 93 additions and 96 deletions
|
@ -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"}
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,68 +350,58 @@ 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;
|
||||
|
||||
// run again with small number of iterations to test invariant checking
|
||||
|
||||
#if !defined(ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED)
|
||||
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)
|
||||
ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
|
||||
#endif
|
||||
|
||||
return saved_g0;
|
||||
return cxt->g0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
SetInvariantChecked(false);
|
||||
TestContext cxt;
|
||||
cxt.mu.EnableInvariantDebugging(invariant, &cxt);
|
||||
int ret = RunTestCommon(&cxt, test, threads, iterations, operations);
|
||||
ABSL_RAW_CHECK(GetInvariantChecked(), "Invariant not checked");
|
||||
absl::EnableMutexInvariantDebugging(false); // Restore.
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Test for fix of bug in TryRemove()
|
||||
struct TimeoutBugStruct {
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue