diff options
author | Thomas Köppe <tkoeppe@google.com> | 2023-04-13 15:04:19 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-04-13 15:05:22 -0700 |
commit | 124e4f4edd1ec2d32193a673f8228f5b5c0ff9fa (patch) | |
tree | a59181f9bb1cfb6ee10b0649dcbdd23eff728401 | |
parent | c5f310de3ba06b7ad24da48145a099485322d2ac (diff) |
Spell out the meaning of non-reentrant/non-recursive.
PiperOrigin-RevId: 524112966
Change-Id: I197f98f95b1c4de7f53295a6a01db9b0379b4f55
-rw-r--r-- | absl/synchronization/mutex.h | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index f793cc0e..148fa191 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -92,26 +92,42 @@ struct SynchWaitParams; // // 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), while the `Unlock()` operation *releases* a +// *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 +// 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 | Free | +// | | 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 `TryLock()` must not be made in a thread that already holds the +// mutex; such a call is invalid. // -// Attempts to `Unlock()` must originate from the thread that performed the -// corresponding `Lock()` operation. +// * 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 is disallowed by the API. The `Mutex` implementation -// is allowed to do anything on an invalid call, including but not limited to +// 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 attempts to crash with a -// useful error message. +// 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 |