Imagine if you had a platform whose native, low-level primitive mutexes do not have a "try lock" operation. In that case, to implement a high-level mutex that does, you'd have to use a condition variable and a boolean "is locked" protected by the low-level mutex to indicate the high-level mutex was locked.
So a waitable mutex could be implemented using a low-level primitive mutex (that does not support a "trylock" operation) to implement a high-level mutex (that does). The "high-level mutex" can just be a boolean that's protected by the low-level mutex.
With that design, mutex_lock
would be implemented as follows:
- Acquire low-level mutex (this is a real lock operation on the primitive, implementation mutex).
- If high-level mutex is held, do a condition wait for the high-level mutex.
- Acquire high-level mutex (just
locked = true;
).
- Release low-level mutex.
And mutex_unlock
would be implemented as follows:
- Acquire low-level mutex.
- Release high-level mutex (just
locked = false;
)
- Signal the condition variable.
- Release the low-level mutex.
In that case, mutex_trylock
would be implemented as follows:
- Acquire low-level mutex.
- Check if high-level mutex is held.
- If so, release low-level mutex and return failure.
- Take high-level mutex.
- Release low-level mutex.
- Return success.
Imagine if we're interrupted after step 2 but before step 3.