pub struct Mutex<T: ?Sized> { /* private fields */ }
Expand description
Holds a T
that can be accessed from multiple concurrent futures/tasks,
but only one at a time.
This implementation is more efficient than a spin-lock, because when the mutex is contended, all competing tasks but one register themselves for waking when the mutex is freed. Thus, nobody needs to spin.
When the mutex is unlocked, the task doing the unlocking will check the mutex’s wait list and release the oldest task on it.
Implementations§
source§impl<T> Mutex<T>
impl<T> Mutex<T>
sourcepub const fn create(contents: T) -> Self
pub const fn create(contents: T) -> Self
Returns a mutex containing contents
. The result must be pinned before
it’s good for much.
sourcepub fn try_lock(self: Pin<&Self>) -> Option<ActionPermit<'_, T>>
pub fn try_lock(self: Pin<&Self>) -> Option<ActionPermit<'_, T>>
Attempts to lock this mutex and return an ActionPermit
if the mutex is
free, but without blocking if the mutex is not free.
If the mutex is free, this returns Some(permit)
, where permit
is an
ActionPermit
granting the ability to perform a single synchronous
action against the guarded data.
If the mutex is not free, returns None
.
This is the cheaper, non-blocking version of Mutex::lock
.
sourcepub unsafe fn unlock(self: Pin<&Self>)
pub unsafe fn unlock(self: Pin<&Self>)
Unlocks the mutex.
Normally, you unlock a mutex by dropping the MutexGuard
that you got
from try_lock
or lock
. That proves that you locked it in the first
place.
unlock
allows you to unlock a mutex you didn’t lock. This can wreak
all sorts of havoc if used incorrectly.
§Safety
You can use this safely only if you know that no other code thinks it
still has the mutex locked, including the code calling unlock
. You
might do this if you have, for instance, used forget
on the
MutexGuard
for some reason.
sourcepub async fn lock(self: Pin<&Self>) -> ActionPermit<'_, T>
pub async fn lock(self: Pin<&Self>) -> ActionPermit<'_, T>
Returns a future that will attempt to lock this mutex, resolving only
when it succeeds. When it resolves, it will produce an ActionPermit
,
granting the ability to perform one synchronous closure to the guarded
data.
If the mutex is free at the time of the first poll
, the future will
resolve cheaply without blocking. Otherwise, it will join the mutex’s
wait-list to avoid waking its task until its turn comes up.
This is the more expensive, blocking version of Mutex::try_lock
.
§This does not return a smart pointer
This operation doesn’t return a “smart pointer” mutex guard that can
Deref
to T
, because that style of API acts as a “bug generator” in
async Rust code that hasn’t carefully thought about cancellation. That
style of API is still available with restrictions, however. See the docs
on Mutex
for more details.
§Cancellation
Cancel safety: Strict.
Dropping the future before it resolves loses its place in line. Dropping it after the mutex is locked passes ownership to the next waiter.
This API is designed to make it easy for you to implement further
strict-cancel-safe operations using Mutex
.
source§impl<T> Mutex<T>
impl<T> Mutex<T>
sourcepub unsafe fn new(contents: T) -> ManuallyDrop<Self>
👎Deprecated since 1.2.0: old-style initialization is complicated, see Mutex::create
pub unsafe fn new(contents: T) -> ManuallyDrop<Self>
Returns an initialized but invalid mutex.
§Safety
The result is not safe to use or drop yet. You must move it to its final
resting place, pin it, and call finish_init
.
sourcepub unsafe fn finish_init(_this: Pin<&mut Self>)
👎Deprecated since 1.2.0: old-style initialization is complicated, see Mutex::create
pub unsafe fn finish_init(_this: Pin<&mut Self>)
Finishes initializing a mutex, discharging obligations from new
.
§Safety
This is safe to call exactly once on the result of new
, after it has
been moved to its final position and pinned.
source§impl<T> Mutex<CancelSafe<T>>
impl<T> Mutex<CancelSafe<T>>
sourcepub fn try_lock_assuming_cancel_safe(
self: Pin<&Self>
) -> Option<MutexGuard<'_, T>>
pub fn try_lock_assuming_cancel_safe( self: Pin<&Self> ) -> Option<MutexGuard<'_, T>>
Locks this mutex immediately if it is free, and returns a guard for
keeping it locked, even across await
points – which means you’re
implicitly asserting that whatever you’re about to do maintains
invariants across cancel points. The Mutex
will assume you’re right
about that.
If the mutex is not free, returns None
.
This API can be error-prone, which is why it’s only available if you’ve
asserted your guarded data is CancelSafe
. When possible, see if you
can do the job using Mutex::try_lock
instead.
sourcepub async fn lock_assuming_cancel_safe(self: Pin<&Self>) -> MutexGuard<'_, T>
pub async fn lock_assuming_cancel_safe(self: Pin<&Self>) -> MutexGuard<'_, T>
Returns a future that will attempt to lock the mutex, resolving only
when it succeeds. When it resolves, it will a MutexGuard
, a “smart
pointer” resource token that represents successfully locking a mutex,
and grants its holder access to the guarded data – even across an
await
point. This means by using this operation, you’re asserting that
what you’re about to do maintains any invariants across cancel points.
The Mutex
will assume you’re right about that.
If the mutex is free at the time of the first poll
, the future will
resolve cheaply without blocking.
§This operation is opt-in
lock_assuming_cancel_safe
is not available on mutexes unless you wrap
the contents in the CancelSafe
marker type. This is because the
traditional Rust mutex API pattern of returning a guard can introduce
surprising problems in async
code. See the docs on Mutex
about
lock
vs lock_assuming_cancel_safe
for more details.
Consider whether you can use the Mutex::lock
operation instead.
§Cancellation
Cancel safety: Strict. No, really. Even with the warning above.
The future returned by lock_assuming_cancel_safe
, and the
MutexGuard
it resolves to, can both be dropped/cancelled at any time
without side effect, and simply calling lock
again works to retry. The
reason this API is behind a guard rail is that that statement isn’t
sufficient: yeah, this is technically strictly cancel-safe, but it
makes it really easy for you to write code on top of it that isn’t.
(It would be great if cancel-safety were purely compositional, so
writing a program in terms of all cancel-safe operations is
automatically cancel-safe; this is not the case.) So, please read the
Mutex
docs carefully before deciding to use this.
Cancellation behavior for the returned future is slightly subtle, but does the right thing for all cases.
- If dropped before it’s polled at all it does essentially nothing.
- If dropped once it’s added itself to the wait list for the mutex, but before it has been given the mutex, it will detach from the wait list.
- If dropped after it has been given the mutex, but before it’s been polled (and thus given a chance to notice that), it will wake the next waiter on the mutex wait list.