#include "absl/synchronization/mutex.h"
#ifdef _WIN32
#include <windows.h>
#endif
#include <algorithm>
#include <atomic>
#include <cstdlib>
#include <functional>
#include <memory>
#include <random>
#include <string>
#include <thread>
#include <type_traits>
#include <vector>
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/synchronization/internal/create_thread_identity.h"
#include "absl/synchronization/internal/thread_pool.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
#include <pthread.h>
#include <string.h>
#endif
namespace {
static constexpr bool kExtendedTest = …;
std::unique_ptr<absl::synchronization_internal::ThreadPool> CreatePool(
int threads) { … }
std::unique_ptr<absl::synchronization_internal::ThreadPool>
CreateDefaultPool() { … }
static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
absl::Duration after,
const std::function<void()> &func) { … }
struct ScopedInvariantDebugging { … };
struct TestContext { … };
static std::atomic<bool> invariant_checked;
static bool GetInvariantChecked() { … }
static void SetInvariantChecked(bool new_value) { … }
static void CheckSumG0G1(void *v) { … }
static void TestMu(TestContext *cxt, int c) { … }
static void TestTry(TestContext *cxt, int c) { … }
static void TestR20ms(TestContext *cxt, int c) { … }
static void TestRW(TestContext *cxt, int c) { … }
struct MyContext { … };
bool MyContext::MyTurn() { … }
static void TestAwait(TestContext *cxt, int c) { … }
static void TestSignalAll(TestContext *cxt, int c) { … }
static void TestSignal(TestContext *cxt, int c) { … }
static void TestCVTimeout(TestContext *cxt, int c) { … }
static bool G0GE2(TestContext *cxt) { … }
static void TestTime(TestContext *cxt, int c, bool use_cv) { … }
static void TestMuTime(TestContext *cxt, int c) { … }
static void TestCVTime(TestContext *cxt, int c) { … }
static void EndTest(int *c0, int *c1, absl::Mutex *mu, absl::CondVar *cv,
const std::function<void(int)> &cb) { … }
static int RunTestCommon(TestContext *cxt, void (*test)(TestContext *cxt, int),
int threads, int iterations, int operations) { … }
static int RunTest(void (*test)(TestContext *cxt, int), int threads,
int iterations, int operations) { … }
#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 *)) { … }
#endif
struct TimeoutBugStruct { … };
static void WaitForA(TimeoutBugStruct *x) { … }
static bool NoAWaiters(TimeoutBugStruct *x) { … }
TEST(Mutex, CondVarWaitSignalsAwait) { … }
TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) { … }
TEST(Mutex, MutexTimeoutBug) { … }
struct CondVarWaitDeadlock : testing::TestWithParam<int> { … };
TEST_P(CondVarWaitDeadlock, Test) { … }
INSTANTIATE_TEST_SUITE_P(…);
struct DequeueAllWakeableBugStruct { … };
static void AcquireAsReader(DequeueAllWakeableBugStruct *x) { … }
TEST(Mutex, MutexReaderWakeupBug) { … }
struct LockWhenTestStruct { … };
static bool LockWhenTestIsCond(LockWhenTestStruct *s) { … }
static void LockWhenTestWaitForIsCond(LockWhenTestStruct *s) { … }
TEST(Mutex, LockWhen) { … }
TEST(Mutex, LockWhenGuard) { … }
#if !defined(ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE)
struct ReaderDecrementBugStruct { … };
static bool IsCond(void *v) { … }
static bool AllDone(void *v) { … }
static void WaitForCond(ReaderDecrementBugStruct *x) { … }
static void GetReadLock(ReaderDecrementBugStruct *x) { … }
TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { … }
#endif
#ifdef ABSL_HAVE_THREAD_SANITIZER
TEST(Mutex, DISABLED_LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
#else
TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { … }
bool Equals42(int *p) { … }
bool Equals43(int *p) { … }
bool ConstEquals42(const int *p) { … }
bool ConstEquals43(const int *p) { … }
template <typename T>
bool TemplateEquals42(T *p) { … }
template <typename T>
bool TemplateEquals43(T *p) { … }
TEST(Mutex, FunctionPointerCondition) { … }
struct Base { … };
struct Derived : Base { … };
bool BaseEquals42(Base *p) { … }
bool BaseEquals43(Base *p) { … }
bool ConstBaseEquals42(const Base *p) { … }
bool ConstBaseEquals43(const Base *p) { … }
TEST(Mutex, FunctionPointerConditionWithDerivedToBaseConversion) { … }
struct Constable { … };
TEST(Mutex, FunctionPointerConditionWithConstMethod) { … }
struct True { … };
struct DerivedTrue : True { … };
TEST(Mutex, FunctorCondition) { … }
TEST(Mutex, ConditionSwap) { … }
static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
int *running) { … }
static bool IntIsZero(int *x) { … }
TEST(Mutex, TestReaderOnCondVar) { … }
struct AcquireFromConditionStruct { … };
static bool ConditionWithAcquire(AcquireFromConditionStruct *x) { … }
static void WaitForCond2(AcquireFromConditionStruct *x) { … }
TEST(Mutex, AcquireFromCondition) { … }
TEST(Mutex, DeadlockDetector) { … }
class ScopedDisableBazelTestWarnings { … };
const char ScopedDisableBazelTestWarnings::kVarName[] = …;
#ifdef ABSL_HAVE_THREAD_SANITIZER
TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
#else
TEST(Mutex, DeadlockDetectorBazelWarning) { … }
TEST(Mutex, DeadlockDetectorLongCycle) { … }
TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS { … }
#ifdef ABSL_HAVE_THREAD_SANITIZER
TEST(Mutex, DISABLED_DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
#else
TEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS { … }
static absl::Duration TimeoutTestAllowedSchedulingDelay() { … }
ABSL_MUST_USE_RESULT
static bool DelayIsWithinBounds(absl::Duration expected_delay,
absl::Duration actual_delay) { … }
struct TimeoutTestParam { … };
std::ostream &operator<<(std::ostream &os, const TimeoutTestParam ¶m) { … }
static void RunAfterDelay(absl::Duration delay,
absl::synchronization_internal::ThreadPool *pool,
const std::function<void()> &callback) { … }
class TimeoutTest : public ::testing::Test,
public ::testing::WithParamInterface<TimeoutTestParam> { … };
std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() { … }
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(TimeoutTest, Await) { … }
TEST_P(TimeoutTest, LockWhen) { … }
TEST_P(TimeoutTest, ReaderLockWhen) { … }
TEST_P(TimeoutTest, Wait) { … }
TEST(Mutex, Logging) { … }
TEST(Mutex, LoggingAddressReuse) { … }
TEST(Mutex, LoggingBankrupcy) { … }
TEST(Mutex, SynchEventRace) { … }
static std::vector<int> AllThreadCountValues() { … }
class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> { … };
INSTANTIATE_TEST_SUITE_P(…);
static int ScaleIterations(int x) { … }
TEST_P(MutexVariableThreadCountTest, Mutex) { … }
TEST_P(MutexVariableThreadCountTest, Try) { … }
TEST_P(MutexVariableThreadCountTest, R20ms) { … }
TEST_P(MutexVariableThreadCountTest, RW) { … }
TEST_P(MutexVariableThreadCountTest, Await) { … }
TEST_P(MutexVariableThreadCountTest, SignalAll) { … }
TEST(Mutex, Signal) { … }
TEST(Mutex, Timed) { … }
TEST(Mutex, CVTime) { … }
TEST(Mutex, MuTime) { … }
TEST(Mutex, SignalExitedThread) { … }
TEST(Mutex, WriterPriority) { … }
#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
TEST(Mutex, CondVarPriority) { … }
#endif
TEST(Mutex, LockWhenWithTimeoutResult) { … }
}