merge(3p/absl): subtree merge of Abseil up to e19260f
... notably, this includes Abseil's own StatusOr type, which conflicted with our implementation (that was taken from TensorFlow). Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
This commit is contained in:
parent
cc27324d02
commit
082c006c04
854 changed files with 11260 additions and 5296 deletions
124
third_party/abseil_cpp/absl/synchronization/mutex.h
vendored
124
third_party/abseil_cpp/absl/synchronization/mutex.h
vendored
|
@ -31,22 +31,23 @@
|
|||
//
|
||||
// MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
|
||||
// write access within the current scope.
|
||||
//
|
||||
// ReaderMutexLock
|
||||
// - An RAII wrapper to acquire and release a `Mutex` for shared/read
|
||||
// access within the current scope.
|
||||
//
|
||||
// WriterMutexLock
|
||||
// - Alias for `MutexLock` above, designed for use in distinguishing
|
||||
// reader and writer locks within code.
|
||||
// - Effectively an alias for `MutexLock` above, designed for use in
|
||||
// distinguishing reader and writer locks within code.
|
||||
//
|
||||
// In addition to simple mutex locks, this file also defines ways to perform
|
||||
// locking under certain conditions.
|
||||
//
|
||||
// Condition - (Preferred) Used to wait for a particular predicate that
|
||||
// depends on state protected by the `Mutex` to become true.
|
||||
// CondVar - A lower-level variant of `Condition` that relies on
|
||||
// application code to explicitly signal the `CondVar` when
|
||||
// a condition has been met.
|
||||
// Condition - (Preferred) Used to wait for a particular predicate that
|
||||
// depends on state protected by the `Mutex` to become true.
|
||||
// CondVar - A lower-level variant of `Condition` that relies on
|
||||
// application code to explicitly signal the `CondVar` when
|
||||
// a condition has been met.
|
||||
//
|
||||
// See below for more information on using `Condition` or `CondVar`.
|
||||
//
|
||||
|
@ -72,15 +73,6 @@
|
|||
#include "absl/synchronization/internal/per_thread_sem.h"
|
||||
#include "absl/time/time.h"
|
||||
|
||||
// Decide if we should use the non-production implementation because
|
||||
// the production implementation hasn't been fully ported yet.
|
||||
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
|
||||
#error ABSL_INTERNAL_USE_NONPROD_MUTEX cannot be directly set
|
||||
#elif defined(ABSL_LOW_LEVEL_ALLOC_MISSING)
|
||||
#define ABSL_INTERNAL_USE_NONPROD_MUTEX 1
|
||||
#include "absl/synchronization/internal/mutex_nonprod.inc"
|
||||
#endif
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
|
@ -461,15 +453,6 @@ class ABSL_LOCKABLE Mutex {
|
|||
static void InternalAttemptToUseMutexInFatalSignalHandler();
|
||||
|
||||
private:
|
||||
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
|
||||
friend class CondVar;
|
||||
|
||||
synchronization_internal::MutexImpl *impl() { return impl_.get(); }
|
||||
|
||||
synchronization_internal::SynchronizationStorage<
|
||||
synchronization_internal::MutexImpl>
|
||||
impl_;
|
||||
#else
|
||||
std::atomic<intptr_t> mu_; // The Mutex state.
|
||||
|
||||
// Post()/Wait() versus associated PerThreadSem; in class for required
|
||||
|
@ -504,7 +487,6 @@ class ABSL_LOCKABLE Mutex {
|
|||
void Trans(MuHow how); // used for CondVar->Mutex transfer
|
||||
void Fer(
|
||||
base_internal::PerThreadSynch *w); // used for CondVar->Mutex transfer
|
||||
#endif
|
||||
|
||||
// Catch the error of writing Mutex when intending MutexLock.
|
||||
Mutex(const volatile Mutex * /*ignored*/) {} // NOLINT(runtime/explicit)
|
||||
|
@ -525,22 +507,36 @@ class ABSL_LOCKABLE Mutex {
|
|||
// Example:
|
||||
//
|
||||
// Class Foo {
|
||||
//
|
||||
// public:
|
||||
// Foo::Bar* Baz() {
|
||||
// MutexLock l(&lock_);
|
||||
// MutexLock lock(&mu_);
|
||||
// ...
|
||||
// return bar;
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// Mutex lock_;
|
||||
// Mutex mu_;
|
||||
// };
|
||||
class ABSL_SCOPED_LOCKABLE MutexLock {
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
// Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
|
||||
// guaranteed to be locked when this object is constructed. Requires that
|
||||
// `mu` be dereferenceable.
|
||||
explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
|
||||
this->mu_->Lock();
|
||||
}
|
||||
|
||||
// Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
|
||||
// the above, the condition given by `cond` is also guaranteed to hold when
|
||||
// this object is constructed.
|
||||
explicit MutexLock(Mutex *mu, const Condition &cond)
|
||||
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||
: mu_(mu) {
|
||||
this->mu_->LockWhen(cond);
|
||||
}
|
||||
|
||||
MutexLock(const MutexLock &) = delete; // NOLINT(runtime/mutex)
|
||||
MutexLock(MutexLock&&) = delete; // NOLINT(runtime/mutex)
|
||||
MutexLock& operator=(const MutexLock&) = delete;
|
||||
|
@ -562,6 +558,12 @@ class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
|
|||
mu->ReaderLock();
|
||||
}
|
||||
|
||||
explicit ReaderMutexLock(Mutex *mu, const Condition &cond)
|
||||
ABSL_SHARED_LOCK_FUNCTION(mu)
|
||||
: mu_(mu) {
|
||||
mu->ReaderLockWhen(cond);
|
||||
}
|
||||
|
||||
ReaderMutexLock(const ReaderMutexLock&) = delete;
|
||||
ReaderMutexLock(ReaderMutexLock&&) = delete;
|
||||
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
|
||||
|
@ -584,6 +586,12 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock {
|
|||
mu->WriterLock();
|
||||
}
|
||||
|
||||
explicit WriterMutexLock(Mutex *mu, const Condition &cond)
|
||||
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||
: mu_(mu) {
|
||||
mu->WriterLockWhen(cond);
|
||||
}
|
||||
|
||||
WriterMutexLock(const WriterMutexLock&) = delete;
|
||||
WriterMutexLock(WriterMutexLock&&) = delete;
|
||||
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
|
||||
|
@ -622,16 +630,26 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock {
|
|||
// `noexcept`; until then this requirement cannot be enforced in the
|
||||
// type system.)
|
||||
//
|
||||
// Note: to use a `Condition`, you need only construct it and pass it within the
|
||||
// appropriate `Mutex' member function, such as `Mutex::Await()`.
|
||||
// Note: to use a `Condition`, you need only construct it and pass it to a
|
||||
// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
|
||||
// constructor of one of the scope guard classes.
|
||||
//
|
||||
// Example:
|
||||
// Example using LockWhen/Unlock:
|
||||
//
|
||||
// // assume count_ is not internal reference count
|
||||
// int count_ ABSL_GUARDED_BY(mu_);
|
||||
// Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
|
||||
//
|
||||
// mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
|
||||
// &count_));
|
||||
// mu_.LockWhen(count_is_zero);
|
||||
// // ...
|
||||
// mu_.Unlock();
|
||||
//
|
||||
// Example using a scope guard:
|
||||
//
|
||||
// {
|
||||
// MutexLock lock(&mu_, count_is_zero);
|
||||
// // ...
|
||||
// }
|
||||
//
|
||||
// When multiple threads are waiting on exactly the same condition, make sure
|
||||
// that they are constructed with the same parameters (same pointer to function
|
||||
|
@ -685,6 +703,11 @@ class Condition {
|
|||
// return processed_ >= current;
|
||||
// };
|
||||
// mu_.Await(Condition(&reached));
|
||||
//
|
||||
// NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
|
||||
// the lambda as it may be called when the mutex is being unlocked from a
|
||||
// scope holding only a reader lock, which will make the assertion not
|
||||
// fulfilled and crash the binary.
|
||||
|
||||
// See class comment for performance advice. In particular, if there
|
||||
// might be more than one waiter for the same condition, make sure
|
||||
|
@ -833,17 +856,10 @@ class CondVar {
|
|||
void EnableDebugLog(const char *name);
|
||||
|
||||
private:
|
||||
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
|
||||
synchronization_internal::CondVarImpl *impl() { return impl_.get(); }
|
||||
synchronization_internal::SynchronizationStorage<
|
||||
synchronization_internal::CondVarImpl>
|
||||
impl_;
|
||||
#else
|
||||
bool WaitCommon(Mutex *mutex, synchronization_internal::KernelTimeout t);
|
||||
void Remove(base_internal::PerThreadSynch *s);
|
||||
void Wakeup(base_internal::PerThreadSynch *w);
|
||||
std::atomic<intptr_t> cv_; // Condition variable state.
|
||||
#endif
|
||||
CondVar(const CondVar&) = delete;
|
||||
CondVar& operator=(const CondVar&) = delete;
|
||||
};
|
||||
|
@ -865,6 +881,15 @@ class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
|
|||
this->mu_->Lock();
|
||||
}
|
||||
}
|
||||
|
||||
explicit MutexLockMaybe(Mutex *mu, const Condition &cond)
|
||||
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||
: mu_(mu) {
|
||||
if (this->mu_ != nullptr) {
|
||||
this->mu_->LockWhen(cond);
|
||||
}
|
||||
}
|
||||
|
||||
~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
|
||||
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
||||
}
|
||||
|
@ -887,6 +912,13 @@ class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
|
|||
: mu_(mu) {
|
||||
this->mu_->Lock();
|
||||
}
|
||||
|
||||
explicit ReleasableMutexLock(Mutex *mu, const Condition &cond)
|
||||
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||
: mu_(mu) {
|
||||
this->mu_->LockWhen(cond);
|
||||
}
|
||||
|
||||
~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
|
||||
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
||||
}
|
||||
|
@ -901,12 +933,6 @@ class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
|
|||
ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
|
||||
};
|
||||
|
||||
#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
|
||||
|
||||
inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
|
||||
|
||||
#else
|
||||
|
||||
inline Mutex::Mutex() : mu_(0) {
|
||||
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
||||
}
|
||||
|
@ -915,8 +941,6 @@ inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
|
|||
|
||||
inline CondVar::CondVar() : cv_(0) {}
|
||||
|
||||
#endif // ABSL_INTERNAL_USE_NONPROD_MUTEX
|
||||
|
||||
// static
|
||||
template <typename T>
|
||||
bool Condition::CastAndCallMethod(const Condition *c) {
|
||||
|
@ -983,7 +1007,7 @@ void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp));
|
|||
//
|
||||
// This has the same memory ordering concerns as RegisterMutexProfiler() above.
|
||||
void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
|
||||
int64_t wait_cycles));
|
||||
int64_t wait_cycles));
|
||||
|
||||
// TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
|
||||
// into a single interface, since they are only ever called in pairs.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue