proxygen
|
#include <Mutex.h>
Classes | |
class | LockOperation |
class | ScopedLockOperation |
Public Member Functions | |
Mutex () noexcept | |
Construct a new async mutex that is initially unlocked. More... | |
Mutex (const Mutex &)=delete | |
Mutex (Mutex &&)=delete | |
Mutex & | operator= (const Mutex &)=delete |
Mutex & | operator= (Mutex &&)=delete |
~Mutex () | |
bool | try_lock () noexcept |
ScopedLockOperation | co_scoped_lock () noexcept |
LockOperation | co_lock () noexcept |
void | unlock () noexcept |
Private Member Functions | |
void * | unlockedState () noexcept |
bool | lockAsyncImpl (LockOperation *awaiter) |
Private Attributes | |
std::atomic< void * > | state_ |
LockOperation * | waiters_ |
Friends | |
class | LockOperation |
A mutex that can be locked asynchronously using 'co_await'.
Ownership of the mutex is not tied to any particular thread. This allows the coroutine owning the lock to transition from one thread to another while holding the lock and then perform the unlock() operation on another thread.
This mutex guarantees a FIFO scheduling algorithm - coroutines acquire the lock in the order that they execute the 'co_await mutex.lockAsync()' operation.
Note that you cannot use std::scoped_lock/std::lock_guard to acquire the lock as the lock must be acquired with use of 'co_await' which cannot be used in a constructor.
You can still use the std::scoped_lock/std::lock_guard in conjunction with std::adopt_lock to automatically unlock the mutex when the current scope exits after having locked the mutex using either co_await m.lock_async() or try_lock() .
You can also attempt to acquire the lock using std::unique_lock in conjunction with std::try_to_lock.
For example: folly::coro::Mutex m; folly::Executor& executor;
folly::coro::Task<> asyncScopedLockExample() { std::unique_lock<folly::coro::Mutex> lock{co_await m.co_scoped_lock()}; ... }
folly::coro::Task<> asyncManualLockAndUnlock() { co_await m.co_lock(executor); ... m.unlock(); }
void nonAsyncTryLock() { if (m.try_lock()) { // Once the lock is acquired you can pass ownership of the lock to // a std::lock_guard object. std::lock_guard<folly::coro::Mutex> lock{m, std::adopt_lock}; ... } }
void nonAsyncScopedTryLock() { std::unique_lock<folly::coro::Mutex> lock{m, std::try_to_lock}; if (lock) { ... } }
|
inlinenoexcept |
Construct a new async mutex that is initially unlocked.
Definition at line 90 of file Mutex.h.
References operator=(), and ~Mutex().
|
delete |
|
delete |
folly::coro::Mutex::~Mutex | ( | ) |
Referenced by Mutex().
|
inlinenoexcept |
Lock the mutex asynchronously.
You must co_await the return value to wait until the lock is acquired.
Chain a call to .via() to specify the executor to resume on when the lock is eventually acquired in the case that the lock could not be acquired synchronously. The awaiting coroutine will continue without suspending if the lock could be acquired synchronously.
Once the 'co_await m.lockAsync()' operation completes, the awaiting coroutine is responsible for ensuring that .unlock() is called to release the lock.
Consider using scopedLockAsync() instead to obtain a std::scoped_lock that handles releasing the lock at the end of the scope.
Definition at line 221 of file Mutex.h.
Referenced by try_lock().
|
inlinenoexcept |
Lock the mutex asynchronously, returning an RAII object that will release the lock at the end of the scope.
You must co_await the return value to wait until the lock is acquired.
Chain a call to .via() to specify the executor to resume on when the lock is eventually acquired in the case that the lock could not be acquired synchronously. The awaiting coroutine will continue without suspending if the lock could be acquired synchronously.
If you do not specify an executor by calling .via() then the inline executor is used and the awaiting coroutine is resumed inline inside the call to .unlock() by the previous lock holder.
Definition at line 217 of file Mutex.h.
Referenced by try_lock().
|
private |
Referenced by folly::coro::Mutex::LockOperation::await_suspend(), and unlockedState().
|
inlinenoexcept |
Try to lock the mutex synchronously.
Returns true if the lock was able to be acquired synchronously, false if the lock could not be acquired because it was already locked.
If this method returns true then the caller is responsible for ensuring that unlock() is called to release the lock.
Definition at line 106 of file Mutex.h.
References co_lock(), co_scoped_lock(), folly::pushmi::__adl::noexcept(), state_, unlock(), and unlockedState().
Referenced by folly::coro::Mutex::LockOperation::await_ready().
|
noexcept |
Unlock the mutex.
If there are other coroutines waiting to lock the mutex then this will schedule the resumption of the next coroutine in the queue.
Referenced by try_lock().
|
inlineprivatenoexcept |
|
friend |
|
private |
Definition at line 210 of file Mutex.h.
Referenced by try_lock().
|
private |