class Mutex
Defined at line 150 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
-----------------------------------------------------------------------------
Mutex
-----------------------------------------------------------------------------
A `Mutex` is a non-reentrant (aka non-recursive) Mutually Exclusive lock
on some resource, typically a variable or data structure with associated
invariants. Proper usage of mutexes prevents concurrent access by different
threads to the same resource.
A `Mutex` has two basic operations: `Mutex::lock()` and `Mutex::unlock()`.
The `lock()` operation *acquires* a `Mutex` (in a state known as an
*exclusive* -- or *write* -- lock), and the `unlock()` operation *releases* a
Mutex. During the span of time between the lock() and unlock() operations,
a mutex is said to be *held*. By design, all mutexes support exclusive/write
locks, as this is the most common way to use a mutex.
Mutex operations are only allowed under certain conditions; otherwise an
operation is "invalid", and disallowed by the API. The conditions concern
both the current state of the mutex and the identity of the threads that
are performing the operations.
The `Mutex` state machine for basic lock/unlock operations is quite simple:
| | lock() | unlock() |
|----------------+------------------------+----------|
| Free | Exclusive | invalid |
| Exclusive | blocks, then exclusive | Free |
The full conditions are as follows.
* Calls to `unlock()` require that the mutex be held, and must be made in the
same thread that performed the corresponding `lock()` operation which
acquired the mutex; otherwise the call is invalid.
* The mutex being non-reentrant (or non-recursive) means that a call to
`lock()` or `try_lock()` must not be made in a thread that already holds
the mutex; such a call is invalid.
* In other words, the state of being "held" has both a temporal component
(from `lock()` until `unlock()`) as well as a thread identity component:
the mutex is held *by a particular thread*.
An "invalid" operation has undefined behavior. The `Mutex` implementation
is allowed to do anything on an invalid call, including, but not limited to,
crashing with a useful error message, silently succeeding, or corrupting
data structures. In debug mode, the implementation may crash with a useful
error message.
`Mutex` is not guaranteed to be "fair" in prioritizing waiting threads; it
is, however, approximately fair over long periods, and starvation-free for
threads at the same priority.
The lock/unlock primitives are now annotated with lock annotations
defined in (base/thread_annotations.h). When writing multi-threaded code,
you should use lock annotations whenever possible to document your lock
synchronization policy. Besides acting as documentation, these annotations
also help compilers or static analysis tools to identify and warn about
issues that could potentially result in race conditions and deadlocks.
For more information about the lock annotations, please see
[Thread Safety
Analysis](http://clang.llvm.org/docs/ThreadSafetyAnalysis.html) in the Clang
documentation.
See also `MutexLock`, below, for scoped `Mutex` acquisition.
Public Methods
void AssertHeld ()
Mutex::AssertHeld()
Require that the mutex be held exclusively (write mode) by this thread.
If the mutex is not currently held by this thread, this function may report
an error (typically by crashing with a diagnostic) or it may do nothing.
This function is intended only as a tool to assist debugging; it doesn't
guarantee correctness.
void AssertReaderHeld ()
Mutex::AssertReaderHeld()
Require that the mutex be held at least in shared mode (read mode) by this
thread.
If the mutex is not currently held by this thread, this function may report
an error (typically by crashing with a diagnostic) or it may do nothing.
This function is intended only as a tool to assist debugging; it doesn't
guarantee correctness.
void EnableInvariantDebugging (void (* _Nullable)(void * _Null_unspecified) invariant, void * _Null_unspecified arg)
Mutex::EnableInvariantDebugging()
If `invariant`!=null and if invariant debugging has been enabled globally,
cause `(*invariant)(arg)` to be called at moments when the invariant for
this `Mutex` should hold (for example: just after acquire, just before
release).
The routine `invariant` should have no side-effects since it is not
guaranteed how many times it will be called; it should check the invariant
and crash if it does not hold. Enabling global invariant debugging may
substantially reduce `Mutex` performance; it should be set only for
non-production runs. Optimization options may also disable invariant
checks.
void EnableDebugLog (const char * _Nullable name)
Mutex::EnableDebugLog()
Cause all subsequent uses of this `Mutex` to be logged via
`ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if no previous
call to `EnableInvariantDebugging()` or `EnableDebugLog()` has been made.
Note: This method substantially reduces `Mutex` performance.
void ForgetDeadlockInfo ()
Mutex::ForgetDeadlockInfo()
Forget any deadlock-detection information previously gathered
about this `Mutex`. Call this method in debug mode when the lock ordering
of a `Mutex` changes.
void AssertNotHeld ()
Mutex::AssertNotHeld()
Return immediately if this thread does not hold this `Mutex` in any
mode; otherwise, may report an error (typically by crashing with a
diagnostic), or may return immediately.
Currently this check is performed only if all of:
- in debug mode
- SetMutexDeadlockDetectionMode() has been set to kReport or kAbort
- number of locks concurrently held by this thread is not large.
are true.
void InternalAttemptToUseMutexInFatalSignalHandler ()
Mutex::InternalAttemptToUseMutexInFatalSignalHandler()
Causes the `Mutex` implementation to prepare itself for re-entry caused by
future use of `Mutex` within a fatal signal handler. This method is
intended for use only for last-ditch attempts to log crash information.
It does not guarantee that attempts to use Mutexes within the handler will
not deadlock; it merely makes other faults less likely.
WARNING: This routine must be invoked from a signal handler, and the
signal handler must either loop forever or terminate the process.
Attempts to return from (or `longjmp` out of) the signal handler once this
call has been made may cause arbitrary program behaviour including
crashes and deadlocks.
void Lock ()
Defined at line 181 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void Unlock ()
Defined at line 190 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool TryLock ()
Defined at line 200 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void ReaderLock ()
Defined at line 255 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void ReaderUnlock ()
Defined at line 265 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool ReaderTryLock ()
Defined at line 275 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void WriterLock ()
Mutex::WriterLock()
Mutex::WriterUnlock()
Mutex::WriterTryLock()
Aliases for `Mutex::Lock()`, `Mutex::Unlock()`, and `Mutex::TryLock()`.
These methods may be used (along with the complementary `Reader*()`
methods) to distinguish simple exclusive `Mutex` usage (`Lock()`,
etc.) from reader/writer lock usage.
Defined at line 300 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void WriterUnlock ()
Defined at line 303 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool WriterTryLock ()
Defined at line 306 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void Await (const Condition & cond)
Mutex::Await()
Unlocks this `Mutex` and blocks until simultaneously both `cond` is `true`
and this `Mutex` can be reacquired, then reacquires this `Mutex` in the
same mode in which it was previously held. If the condition is initially
`true`, `Await()` *may* skip the release/re-acquire step.
`Await()` requires that this thread holds this `Mutex` in some mode.
Defined at line 351 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void LockWhen (const Condition & cond)
Mutex::LockWhen()
Mutex::ReaderLockWhen()
Mutex::WriterLockWhen()
Blocks until simultaneously both `cond` is `true` and this `Mutex` can
be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
logically equivalent to `*Lock(); Await();` though they may have different
performance characteristics.
Defined at line 363 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void ReaderLockWhen (const Condition & cond)
Defined at line 368 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void WriterLockWhen (const Condition & cond)
Defined at line 373 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool AwaitWithTimeout (const Condition & cond, absl::Duration timeout)
Mutex::AwaitWithTimeout()
Mutex::AwaitWithDeadline()
Unlocks this `Mutex` and blocks until simultaneously:
- either `cond` is true or the {timeout has expired, deadline has passed}
and
- this `Mutex` can be reacquired,
then reacquire this `Mutex` in the same mode in which it was previously
held, returning `true` iff `cond` is `true` on return.
If the condition is initially `true`, the implementation *may* skip the
release/re-acquire step and return immediately.
Deadlines in the past are equivalent to an immediate deadline.
Negative timeouts are equivalent to a zero timeout.
This method requires that this thread holds this `Mutex` in some mode.
Defined at line 398 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool AwaitWithDeadline (const Condition & cond, absl::Time deadline)
Defined at line 402 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool LockWhenWithTimeout (const Condition & cond, absl::Duration timeout)
Mutex::LockWhenWithTimeout()
Mutex::ReaderLockWhenWithTimeout()
Mutex::WriterLockWhenWithTimeout()
Blocks until simultaneously both:
- either `cond` is `true` or the timeout has expired, and
- this `Mutex` can be acquired,
then atomically acquires this `Mutex`, returning `true` iff `cond` is
`true` on return.
Negative timeouts are equivalent to a zero timeout.
Defined at line 417 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool ReaderLockWhenWithTimeout (const Condition & cond, absl::Duration timeout)
Defined at line 422 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool WriterLockWhenWithTimeout (const Condition & cond, absl::Duration timeout)
Defined at line 427 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool LockWhenWithDeadline (const Condition & cond, absl::Time deadline)
Mutex::LockWhenWithDeadline()
Mutex::ReaderLockWhenWithDeadline()
Mutex::WriterLockWhenWithDeadline()
Blocks until simultaneously both:
- either `cond` is `true` or the deadline has been passed, and
- this `Mutex` can be acquired,
then atomically acquires this Mutex, returning `true` iff `cond` is `true`
on return.
Deadlines in the past are equivalent to an immediate deadline.
Defined at line 443 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool ReaderLockWhenWithDeadline (const Condition & cond, absl::Time deadline)
Defined at line 448 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
bool WriterLockWhenWithDeadline (const Condition & cond, absl::Time deadline)
Defined at line 453 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void Mutex ()
Creates a `Mutex` that is not held by anyone. This constructor is
typically used for Mutexes allocated on the heap or the stack.
To create `Mutex` instances with static storage duration
(e.g. a namespace-scoped or global variable), see
`Mutex::Mutex(absl::kConstInit)` below instead.
Defined at line 1156 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void Mutex (absl::ConstInitType )
Creates a mutex with static storage duration. A global variable
constructed this way avoids the lifetime issues that can occur on program
startup and shutdown. (See absl/base/const_init.h.)
For Mutexes allocated on the heap and stack, instead use the default
constructor, which can interact more fully with the thread sanitizer.
Example usage:
namespace foo {
ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit);
}
Defined at line 1160 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void ~Mutex ()
Defined at line 1163 of file ../../third_party/abseil-cpp/src/absl/synchronization/mutex.h
void lock ()
Mutex::lock()
Blocks the calling thread, if necessary, until this `Mutex` is free, and
then acquires it exclusively. (This lock is also known as a "write lock.")
void unlock ()
Mutex::unlock()
Releases this `Mutex` and returns it from the exclusive/write state to the
free state. Calling thread must hold the `Mutex` exclusively.
bool try_lock ()
Mutex::try_lock()
If the mutex can be acquired without blocking, does so exclusively and
returns `true`. Otherwise, returns `false`. Returns `true` with high
probability if the `Mutex` was free.
void lock_shared ()
Mutex::lock_shared()
Blocks the calling thread, if necessary, until this `Mutex` is either free,
or in shared mode, and then acquires a share of it. Note that
`lock_shared()` will block if some other thread has an exclusive/writer
lock on the mutex.
void unlock_shared ()
Mutex::unlock_shared()
Releases a read share of this `Mutex`. `unlock_shared` may return a mutex
to the free state if this thread holds the last reader lock on the mutex.
Note that you cannot call `unlock_shared()` on a mutex held in write mode.
bool try_lock_shared ()
Mutex::try_lock_shared()
If the mutex can be acquired without blocking, acquires this mutex for
shared access and returns `true`. Otherwise, returns `false`. Returns
`true` with high probability if the `Mutex` was free or shared.
Friends
class CondVar