Struct lilos::mutex::Mutex

source ·
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>

source

pub const fn create(contents: T) -> Self

Returns a mutex containing contents. The result must be pinned before it’s good for much.

source

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.

source

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.

source

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>

source

pub unsafe fn new(contents: T) -> ManuallyDrop<Self>

👎Deprecated since 1.2.0: old-style initialization is complicated, see Mutex::create

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.

source

pub unsafe fn finish_init(_this: Pin<&mut Self>)

👎Deprecated since 1.2.0: old-style initialization is complicated, see Mutex::create

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>>

source

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.

source

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.

Trait Implementations§

source§

impl<T: Debug + ?Sized> Debug for Mutex<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'pin, T: ?Sized> Unpin for Mutex<T>
where __Mutex<'pin, T>: Unpin,

Auto Trait Implementations§

§

impl<T> !Freeze for Mutex<T>

§

impl<T> !RefUnwindSafe for Mutex<T>

§

impl<T> !Send for Mutex<T>

§

impl<T> !Sync for Mutex<T>

§

impl<T> !UnwindSafe for Mutex<T>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<U, T> Captures<T> for U
where U: ?Sized,

source§

impl<U, T> Captures<T> for U
where U: ?Sized,