async_mutex
The async_mutex is a merger of a std::mutex and a std::lock_guard.
The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple _coroutines_.
mutex offers exclusive, non-recursive ownership semantics:
With async_mutex, non-recursive and locking multiple times in the same thread are different. Multiple independent coroutines in the same thread can attempt to acquire the async_mutex. Although, if a coroutine acquires the lock, that same coroutine or any coroutines it is currently co_await``ing (to any depth) cannot attempt to acquire the ``async_mutex. This will lead to a deadlock.
A calling _coroutine_ owns a mutex from the time that it successfully calls either _operator co_await_ or try_lock until it calls unlock.
When a _coroutine_ owns a mutex, all other _coroutines_ will block (for calls to _operator co_await_) or receive a false return value (for try_lock) if they attempt to claim ownership of the mutex.
A calling _coroutine or dependents on the coroutine_ must not own the mutex prior to calling _operator co_await_ or try_lock.
The behavior of a program is undefined if a mutex is destroyed while still owned by any threads, or a thread terminates while owning a mutex.
mutex is neither copyable nor movable.
With regards to the return value of operator co_await, async_lock_guard:
The class lock_guard is a mutex wrapper that provides a convenient RAII-style mechanism for owning a mutex for the duration of a scoped block.
When a lock_guard object is created, it attempts to take ownership of the mutex it is given. When control leaves the scope in which the lock_guard object was created, the lock_guard is destructed and the mutex is released.
The lock_guard class is non-copyable.
struct ProectedObject {
    async_mutex mtx_;
    int needs_protecting_;
}
async_function<>
set_value(ProectedObject _object, int _value)
{
    /* suspend until we can get the lock */
    async_lock_guard lock = co_await _object.mtx_;
    /* We can safely edit the value      */
    _object.needs_protecting_ = _value;
    /* We can safely exhibit asynchronous behavior without deadlocks */
    co_await yield();
    /* lock will be released by RAII                           */
    /* Note: resumption of blocked coroutines is not done here */
    /* Resumption is yielded and performed later...            */
}
- 
class zab::async_mutex
 Public Functions
- 
async_mutex(const async_mutex &_engine) = delete
 
- 
async_mutex(async_mutex &_engine) = delete
 
- 
~async_mutex() = default
 
- 
inline bool try_lock() noexcept
 
- 
inline void unlock() noexcept
 
- 
inline auto operator co_await() noexcept
 lock()
- Returns
 Locks the mutex.
- 
struct async_lock_guard
 Public Functions
- 
inline ~async_lock_guard()
 
- 
inline async_lock_guard(async_binary_semaphore *_sem)
 
- 
async_lock_guard(const async_lock_guard &_copy) = delete
 
- 
inline async_lock_guard(async_lock_guard &&_move)
 
Public Members
- 
async_binary_semaphore *sem_
 
- 
inline ~async_lock_guard()
 
- 
async_mutex(const async_mutex &_engine) = delete