aboutsummaryrefslogtreecommitdiff
path: root/absl/synchronization
diff options
context:
space:
mode:
Diffstat (limited to 'absl/synchronization')
-rw-r--r--absl/synchronization/BUILD.bazel13
-rw-r--r--absl/synchronization/CMakeLists.txt17
-rw-r--r--absl/synchronization/internal/thread_pool.h9
-rw-r--r--absl/synchronization/lifetime_test.cc6
-rw-r--r--absl/synchronization/mutex.cc84
-rw-r--r--absl/synchronization/mutex.h108
-rw-r--r--absl/synchronization/mutex_method_pointer_test.cc138
-rw-r--r--absl/synchronization/mutex_test.cc20
8 files changed, 317 insertions, 78 deletions
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 66bd8742..ccaee796 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -200,6 +200,7 @@ cc_library(
deps = [
":synchronization",
"//absl/base:core_headers",
+ "//absl/functional:any_invocable",
],
)
@@ -223,6 +224,18 @@ cc_test(
],
)
+cc_test(
+ name = "mutex_method_pointer_test",
+ srcs = ["mutex_method_pointer_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":synchronization",
+ "//absl/base:config",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
cc_library(
name = "mutex_benchmark_common",
testonly = 1,
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index 9335c264..f64653bb 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -136,8 +136,9 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::synchronization
+ absl::any_invocable
absl::core_headers
+ absl::synchronization
TESTONLY
)
@@ -162,6 +163,20 @@ absl_cc_test(
absl_cc_test(
NAME
+ mutex_method_pointer_test
+ SRCS
+ "mutex_method_pointer_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
+ DEPS
+ absl::base
+ absl::config
+ absl::synchronization
+ GTest::gmock_main
+)
+
+absl_cc_test(
+ NAME
notification_test
SRCS
"notification_test.cc"
diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h
index 0cb96dac..5eb0bb60 100644
--- a/absl/synchronization/internal/thread_pool.h
+++ b/absl/synchronization/internal/thread_pool.h
@@ -20,9 +20,11 @@
#include <functional>
#include <queue>
#include <thread> // NOLINT(build/c++11)
+#include <utility>
#include <vector>
#include "absl/base/thread_annotations.h"
+#include "absl/functional/any_invocable.h"
#include "absl/synchronization/mutex.h"
namespace absl {
@@ -33,6 +35,7 @@ namespace synchronization_internal {
class ThreadPool {
public:
explicit ThreadPool(int num_threads) {
+ threads_.reserve(num_threads);
for (int i = 0; i < num_threads; ++i) {
threads_.push_back(std::thread(&ThreadPool::WorkLoop, this));
}
@@ -54,7 +57,7 @@ class ThreadPool {
}
// Schedule a function to be run on a ThreadPool thread immediately.
- void Schedule(std::function<void()> func) {
+ void Schedule(absl::AnyInvocable<void()> func) {
assert(func != nullptr);
absl::MutexLock l(&mu_);
queue_.push(std::move(func));
@@ -67,7 +70,7 @@ class ThreadPool {
void WorkLoop() {
while (true) {
- std::function<void()> func;
+ absl::AnyInvocable<void()> func;
{
absl::MutexLock l(&mu_);
mu_.Await(absl::Condition(this, &ThreadPool::WorkAvailable));
@@ -82,7 +85,7 @@ class ThreadPool {
}
absl::Mutex mu_;
- std::queue<std::function<void()>> queue_ ABSL_GUARDED_BY(mu_);
+ std::queue<absl::AnyInvocable<void()>> queue_ ABSL_GUARDED_BY(mu_);
std::vector<std::thread> threads_;
};
diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc
index cc973a32..e6274232 100644
--- a/absl/synchronization/lifetime_test.cc
+++ b/absl/synchronization/lifetime_test.cc
@@ -123,10 +123,10 @@ class OnDestruction {
};
// These tests require that the compiler correctly supports C++11 constant
-// initialization... but MSVC has a known regression since v19.10:
+// initialization... but MSVC has a known regression since v19.10 till v19.25:
// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
-// TODO(epastor): Limit the affected range once MSVC fixes this bug.
-#if defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)
+#if defined(__clang__) || \
+ !(defined(_MSC_VER) && _MSC_VER > 1900 && _MSC_VER < 1925)
// kConstInit
// Test early usage. (Declaration comes first; definitions must appear after
// the test runner.)
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 69103ed8..c9d7c41a 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -37,6 +37,8 @@
#include <atomic>
#include <cinttypes>
#include <cstddef>
+#include <cstring>
+#include <iterator>
#include <thread> // NOLINT(build/c++11)
#include "absl/base/attributes.h"
@@ -135,25 +137,42 @@ enum DelayMode { AGGRESSIVE, GENTLE };
struct ABSL_CACHELINE_ALIGNED MutexGlobals {
absl::once_flag once;
int spinloop_iterations = 0;
- int32_t mutex_sleep_limit[2] = {};
+ int32_t mutex_sleep_spins[2] = {};
+ absl::Duration mutex_sleep_time;
};
+absl::Duration MeasureTimeToYield() {
+ absl::Time before = absl::Now();
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
+ return absl::Now() - before;
+}
+
const MutexGlobals &GetMutexGlobals() {
ABSL_CONST_INIT static MutexGlobals data;
absl::base_internal::LowLevelCallOnce(&data.once, [&]() {
const int num_cpus = absl::base_internal::NumCPUs();
data.spinloop_iterations = num_cpus > 1 ? 1500 : 0;
- // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
+ // If this a uniprocessor, only yield/sleep.
+ // Real-time threads are often unable to yield, so the sleep time needs
+ // to be long enough to keep the calling thread asleep until scheduling
+ // happens.
+ // If this is multiprocessor, allow spinning. If the mode is
// aggressive then spin many times before yielding. If the mode is
// gentle then spin only a few times before yielding. Aggressive spinning
// is used to ensure that an Unlock() call, which must get the spin lock
// for any thread to make progress gets it without undue delay.
if (num_cpus > 1) {
- data.mutex_sleep_limit[AGGRESSIVE] = 5000;
- data.mutex_sleep_limit[GENTLE] = 250;
+ data.mutex_sleep_spins[AGGRESSIVE] = 5000;
+ data.mutex_sleep_spins[GENTLE] = 250;
+ data.mutex_sleep_time = absl::Microseconds(10);
} else {
- data.mutex_sleep_limit[AGGRESSIVE] = 0;
- data.mutex_sleep_limit[GENTLE] = 0;
+ data.mutex_sleep_spins[AGGRESSIVE] = 0;
+ data.mutex_sleep_spins[GENTLE] = 0;
+ data.mutex_sleep_time = MeasureTimeToYield() * 5;
+ data.mutex_sleep_time =
+ std::min(data.mutex_sleep_time, absl::Milliseconds(1));
+ data.mutex_sleep_time =
+ std::max(data.mutex_sleep_time, absl::Microseconds(10));
}
});
return data;
@@ -164,7 +183,8 @@ namespace synchronization_internal {
// Returns the Mutex delay on iteration `c` depending on the given `mode`.
// The returned value should be used as `c` for the next call to `MutexDelay`.
int MutexDelay(int32_t c, int mode) {
- const int32_t limit = GetMutexGlobals().mutex_sleep_limit[mode];
+ const int32_t limit = GetMutexGlobals().mutex_sleep_spins[mode];
+ const absl::Duration sleep_time = GetMutexGlobals().mutex_sleep_time;
if (c < limit) {
// Spin.
c++;
@@ -177,7 +197,7 @@ int MutexDelay(int32_t c, int mode) {
c++;
} else {
// Then wait.
- absl::SleepFor(absl::Microseconds(10));
+ absl::SleepFor(sleep_time);
c = 0;
}
ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
@@ -571,10 +591,15 @@ static SynchLocksHeld *Synch_GetAllLocks() {
void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
if (mu) {
ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
- }
- PerThreadSem::Post(w->thread_identity());
- if (mu) {
+ // We miss synchronization around passing PerThreadSynch between threads
+ // since it happens inside of the Mutex code, so we need to ignore all
+ // accesses to the object.
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ PerThreadSem::Post(w->thread_identity());
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
+ } else {
+ PerThreadSem::Post(w->thread_identity());
}
}
@@ -2762,25 +2787,31 @@ static bool Dereference(void *arg) {
return *(static_cast<bool *>(arg));
}
-Condition::Condition() {} // null constructor, used for kTrue only
-const Condition Condition::kTrue;
+ABSL_CONST_INIT const Condition Condition::kTrue;
Condition::Condition(bool (*func)(void *), void *arg)
: eval_(&CallVoidPtrFunction),
- function_(func),
- method_(nullptr),
- arg_(arg) {}
+ arg_(arg) {
+ static_assert(sizeof(&func) <= sizeof(callback_),
+ "An overlarge function pointer passed to Condition.");
+ StoreCallback(func);
+}
bool Condition::CallVoidPtrFunction(const Condition *c) {
- return (*c->function_)(c->arg_);
+ using FunctionPointer = bool (*)(void *);
+ FunctionPointer function_pointer;
+ std::memcpy(&function_pointer, c->callback_, sizeof(function_pointer));
+ return (*function_pointer)(c->arg_);
}
Condition::Condition(const bool *cond)
: eval_(CallVoidPtrFunction),
- function_(Dereference),
- method_(nullptr),
// const_cast is safe since Dereference does not modify arg
- arg_(const_cast<bool *>(cond)) {}
+ arg_(const_cast<bool *>(cond)) {
+ using FunctionPointer = bool (*)(void *);
+ const FunctionPointer dereference = Dereference;
+ StoreCallback(dereference);
+}
bool Condition::Eval() const {
// eval_ == null for kTrue
@@ -2788,14 +2819,15 @@ bool Condition::Eval() const {
}
bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) {
- if (a == nullptr) {
+ // kTrue logic.
+ if (a == nullptr || a->eval_ == nullptr) {
return b == nullptr || b->eval_ == nullptr;
+ }else if (b == nullptr || b->eval_ == nullptr) {
+ return false;
}
- if (b == nullptr || b->eval_ == nullptr) {
- return a->eval_ == nullptr;
- }
- return a->eval_ == b->eval_ && a->function_ == b->function_ &&
- a->arg_ == b->arg_ && a->method_ == b->method_;
+ // Check equality of the representative fields.
+ return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&
+ !memcmp(a->callback_, b->callback_, sizeof(a->callback_));
}
ABSL_NAMESPACE_END
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 8694bb75..c6a85100 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -60,6 +60,8 @@
#include <atomic>
#include <cstdint>
+#include <cstring>
+#include <iterator>
#include <string>
#include "absl/base/const_init.h"
@@ -612,12 +614,12 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock {
// Condition
// -----------------------------------------------------------------------------
//
-// As noted above, `Mutex` contains a number of member functions which take a
-// `Condition` as an argument; clients can wait for conditions to become `true`
-// before attempting to acquire the mutex. These sections are known as
-// "condition critical" sections. To use a `Condition`, you simply need to
-// construct it, and use within an appropriate `Mutex` member function;
-// everything else in the `Condition` class is an implementation detail.
+// `Mutex` contains a number of member functions which take a `Condition` as an
+// argument; clients can wait for conditions to become `true` before attempting
+// to acquire the mutex. These sections are known as "condition critical"
+// sections. To use a `Condition`, you simply need to construct it, and use
+// within an appropriate `Mutex` member function; everything else in the
+// `Condition` class is an implementation detail.
//
// A `Condition` is specified as a function pointer which returns a boolean.
// `Condition` functions should be pure functions -- their results should depend
@@ -727,7 +729,7 @@ class Condition {
: Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}
// A Condition that always returns `true`.
- static const Condition kTrue;
+ ABSL_CONST_INIT static const Condition kTrue;
// Evaluates the condition.
bool Eval() const;
@@ -742,22 +744,54 @@ class Condition {
static bool GuaranteedEqual(const Condition *a, const Condition *b);
private:
- typedef bool (*InternalFunctionType)(void * arg);
- typedef bool (Condition::*InternalMethodType)();
- typedef bool (*InternalMethodCallerType)(void * arg,
- InternalMethodType internal_method);
-
- bool (*eval_)(const Condition*); // Actual evaluator
- InternalFunctionType function_; // function taking pointer returning bool
- InternalMethodType method_; // method returning bool
- void *arg_; // arg of function_ or object of method_
-
- Condition(); // null constructor used only to create kTrue
+ // Sizing an allocation for a method pointer can be subtle. In the Itanium
+ // specifications, a method pointer has a predictable, uniform size. On the
+ // other hand, MSVC ABI, method pointer sizes vary based on the
+ // inheritance of the class. Specifically, method pointers from classes with
+ // multiple inheritance are bigger than those of classes with single
+ // inheritance. Other variations also exist.
+
+#ifndef _MSC_VER
+ // Allocation for a function pointer or method pointer.
+ // The {0} initializer ensures that all unused bytes of this buffer are
+ // always zeroed out. This is necessary, because GuaranteedEqual() compares
+ // all of the bytes, unaware of which bytes are relevant to a given `eval_`.
+ using MethodPtr = bool (Condition::*)();
+ char callback_[sizeof(MethodPtr)] = {0};
+#else
+ // It is well known that the larget MSVC pointer-to-member is 24 bytes. This
+ // may be the largest known pointer-to-member of any platform. For this
+ // reason we will allocate 24 bytes for MSVC platform toolchains.
+ char callback_[24] = {0};
+#endif
+
+ // Function with which to evaluate callbacks and/or arguments.
+ bool (*eval_)(const Condition*) = nullptr;
+
+ // Either an argument for a function call or an object for a method call.
+ void *arg_ = nullptr;
// Various functions eval_ can point to:
static bool CallVoidPtrFunction(const Condition*);
template <typename T> static bool CastAndCallFunction(const Condition* c);
template <typename T> static bool CastAndCallMethod(const Condition* c);
+
+ // Helper methods for storing, validating, and reading callback arguments.
+ template <typename T>
+ inline void StoreCallback(T callback) {
+ static_assert(
+ sizeof(callback) <= sizeof(callback_),
+ "An overlarge pointer was passed as a callback to Condition.");
+ std::memcpy(callback_, &callback, sizeof(callback));
+ }
+
+ template <typename T>
+ inline void ReadCallback(T *callback) const {
+ std::memcpy(callback, callback_, sizeof(*callback));
+ }
+
+ // Used only to create kTrue.
+ constexpr Condition() = default;
};
// -----------------------------------------------------------------------------
@@ -949,44 +983,48 @@ inline CondVar::CondVar() : cv_(0) {}
// static
template <typename T>
bool Condition::CastAndCallMethod(const Condition *c) {
- typedef bool (T::*MemberType)();
- MemberType rm = reinterpret_cast<MemberType>(c->method_);
- T *x = static_cast<T *>(c->arg_);
- return (x->*rm)();
+ T *object = static_cast<T *>(c->arg_);
+ bool (T::*method_pointer)();
+ c->ReadCallback(&method_pointer);
+ return (object->*method_pointer)();
}
// static
template <typename T>
bool Condition::CastAndCallFunction(const Condition *c) {
- typedef bool (*FuncType)(T *);
- FuncType fn = reinterpret_cast<FuncType>(c->function_);
- T *x = static_cast<T *>(c->arg_);
- return (*fn)(x);
+ bool (*function)(T *);
+ c->ReadCallback(&function);
+ T *argument = static_cast<T *>(c->arg_);
+ return (*function)(argument);
}
template <typename T>
inline Condition::Condition(bool (*func)(T *), T *arg)
: eval_(&CastAndCallFunction<T>),
- function_(reinterpret_cast<InternalFunctionType>(func)),
- method_(nullptr),
- arg_(const_cast<void *>(static_cast<const void *>(arg))) {}
+ arg_(const_cast<void *>(static_cast<const void *>(arg))) {
+ static_assert(sizeof(&func) <= sizeof(callback_),
+ "An overlarge function pointer was passed to Condition.");
+ StoreCallback(func);
+}
template <typename T>
inline Condition::Condition(T *object,
bool (absl::internal::identity<T>::type::*method)())
: eval_(&CastAndCallMethod<T>),
- function_(nullptr),
- method_(reinterpret_cast<InternalMethodType>(method)),
- arg_(object) {}
+ arg_(object) {
+ static_assert(sizeof(&method) <= sizeof(callback_),
+ "An overlarge method pointer was passed to Condition.");
+ StoreCallback(method);
+}
template <typename T>
inline Condition::Condition(const T *object,
bool (absl::internal::identity<T>::type::*method)()
const)
: eval_(&CastAndCallMethod<T>),
- function_(nullptr),
- method_(reinterpret_cast<InternalMethodType>(method)),
- arg_(reinterpret_cast<void *>(const_cast<T *>(object))) {}
+ arg_(reinterpret_cast<void *>(const_cast<T *>(object))) {
+ StoreCallback(method);
+}
// Register hooks for profiling support.
//
diff --git a/absl/synchronization/mutex_method_pointer_test.cc b/absl/synchronization/mutex_method_pointer_test.cc
new file mode 100644
index 00000000..1ec801a0
--- /dev/null
+++ b/absl/synchronization/mutex_method_pointer_test.cc
@@ -0,0 +1,138 @@
+// Copyright 2017 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/synchronization/mutex.h"
+
+#include <cstdlib>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace {
+
+class IncompleteClass;
+
+#ifdef _MSC_VER
+// These tests verify expectations about sizes of MSVC pointers to methods.
+// Pointers to methods are distinguished by whether their class hierachies
+// contain single inheritance, multiple inheritance, or virtual inheritence.
+
+// Declare classes of the various MSVC inheritance types.
+class __single_inheritance SingleInheritance{};
+class __multiple_inheritance MultipleInheritance;
+class __virtual_inheritance VirtualInheritance;
+
+TEST(MutexMethodPointerTest, MicrosoftMethodPointerSize) {
+ void (SingleInheritance::*single_inheritance_method_pointer)();
+ void (MultipleInheritance::*multiple_inheritance_method_pointer)();
+ void (VirtualInheritance::*virtual_inheritance_method_pointer)();
+
+#if defined(_M_IX86) || defined(_M_ARM)
+ static_assert(sizeof(single_inheritance_method_pointer) == 4,
+ "Unexpected sizeof(single_inheritance_method_pointer).");
+ static_assert(sizeof(multiple_inheritance_method_pointer) == 8,
+ "Unexpected sizeof(multiple_inheritance_method_pointer).");
+ static_assert(sizeof(virtual_inheritance_method_pointer) == 12,
+ "Unexpected sizeof(virtual_inheritance_method_pointer).");
+#elif defined(_M_X64) || defined(__aarch64__)
+ static_assert(sizeof(single_inheritance_method_pointer) == 8,
+ "Unexpected sizeof(single_inheritance_method_pointer).");
+ static_assert(sizeof(multiple_inheritance_method_pointer) == 16,
+ "Unexpected sizeof(multiple_inheritance_method_pointer).");
+ static_assert(sizeof(virtual_inheritance_method_pointer) == 16,
+ "Unexpected sizeof(virtual_inheritance_method_pointer).");
+#endif
+ void (IncompleteClass::*incomplete_class_method_pointer)();
+ static_assert(sizeof(incomplete_class_method_pointer) >=
+ sizeof(virtual_inheritance_method_pointer),
+ "Failed invariant: sizeof(incomplete_class_method_pointer) >= "
+ "sizeof(virtual_inheritance_method_pointer)!");
+}
+
+class Callback {
+ bool x = true;
+
+ public:
+ Callback() {}
+ bool method() {
+ x = !x;
+ return x;
+ }
+};
+
+class M2 {
+ bool x = true;
+
+ public:
+ M2() {}
+ bool method2() {
+ x = !x;
+ return x;
+ }
+};
+
+class MultipleInheritance : public Callback, public M2 {};
+
+TEST(MutexMethodPointerTest, ConditionWithMultipleInheritanceMethod) {
+ // This test ensures that Condition can deal with method pointers from classes
+ // with multiple inheritance.
+ MultipleInheritance object = MultipleInheritance();
+ absl::Condition condition(&object, &MultipleInheritance::method);
+ EXPECT_FALSE(condition.Eval());
+ EXPECT_TRUE(condition.Eval());
+}
+
+class __virtual_inheritance VirtualInheritance : virtual public Callback {
+ bool x = false;
+
+ public:
+ VirtualInheritance() {}
+ bool method() {
+ x = !x;
+ return x;
+ }
+};
+
+TEST(MutexMethodPointerTest, ConditionWithVirtualInheritanceMethod) {
+ // This test ensures that Condition can deal with method pointers from classes
+ // with virtual inheritance.
+ VirtualInheritance object = VirtualInheritance();
+ absl::Condition condition(&object, &VirtualInheritance::method);
+ EXPECT_TRUE(condition.Eval());
+ EXPECT_FALSE(condition.Eval());
+}
+#endif // #ifdef _MSC_VER
+
+TEST(MutexMethodPointerTest, ConditionWithIncompleteClassMethod) {
+ using IncompleteClassMethodPointer = void (IncompleteClass::*)();
+
+ union CallbackSlot {
+ void (*anonymous_function_pointer)();
+ IncompleteClassMethodPointer incomplete_class_method_pointer;
+ };
+
+ static_assert(sizeof(CallbackSlot) >= sizeof(IncompleteClassMethodPointer),
+ "The callback slot is not big enough for method pointers.");
+ static_assert(
+ sizeof(CallbackSlot) == sizeof(IncompleteClassMethodPointer),
+ "The callback slot is not big enough for anonymous function pointers.");
+
+#if defined(_MSC_VER)
+ static_assert(sizeof(IncompleteClassMethodPointer) <= 24,
+ "The pointer to a method of an incomplete class is too big.");
+#endif
+}
+
+} // namespace
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 99bb0175..34751cb1 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -295,8 +295,9 @@ static void TestTime(TestContext *cxt, int c, bool use_cv) {
"TestTime failed");
}
elapsed = absl::Now() - start;
- ABSL_RAW_CHECK(absl::Seconds(0.9) <= elapsed &&
- elapsed <= absl::Seconds(2.0), "TestTime failed");
+ ABSL_RAW_CHECK(
+ absl::Seconds(0.9) <= elapsed && elapsed <= absl::Seconds(2.0),
+ "TestTime failed");
ABSL_RAW_CHECK(cxt->g0 == cxt->threads, "TestTime failed");
} else if (c == 1) {
@@ -343,7 +344,7 @@ static void TestMuTime(TestContext *cxt, int c) { TestTime(cxt, c, false); }
static void TestCVTime(TestContext *cxt, int c) { TestTime(cxt, c, true); }
static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
- const std::function<void(int)>& cb) {
+ const std::function<void(int)> &cb) {
mu->Lock();
int c = (*c0)++;
mu->Unlock();
@@ -366,9 +367,9 @@ static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
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))));
+ 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) {
@@ -682,14 +683,14 @@ struct LockWhenTestStruct {
bool waiting = false;
};
-static bool LockWhenTestIsCond(LockWhenTestStruct* s) {
+static bool LockWhenTestIsCond(LockWhenTestStruct *s) {
s->mu2.Lock();
s->waiting = true;
s->mu2.Unlock();
return s->cond;
}
-static void LockWhenTestWaitForIsCond(LockWhenTestStruct* s) {
+static void LockWhenTestWaitForIsCond(LockWhenTestStruct *s) {
s->mu1.LockWhen(absl::Condition(&LockWhenTestIsCond, s));
s->mu1.Unlock();
}
@@ -1694,8 +1695,7 @@ TEST(Mutex, Timed) {
TEST(Mutex, CVTime) {
int threads = 10; // Use a fixed thread count of 10
int iterations = 1;
- EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1),
- threads * iterations);
+ EXPECT_EQ(RunTest(&TestCVTime, threads, iterations, 1), threads * iterations);
}
TEST(Mutex, MuTime) {