Skip to main content

BorrowMutex

Struct BorrowMutex 

Source
pub struct BorrowMutex<const MAX_BORROWERS: usize, T: ?Sized> { /* private fields */ }
Expand description

Async Mutex which does not require wrapping the target structure. A &mut T can be lended to the mutex at any given time.

This lets any other side borrow the &mut T. The mutable ref is borrow-able only while the lender awaits, and the lending side can await until someone wants to borrow. The semantics enforce at most one side has a mutable reference at any given time.

This lets us share any mutable object between distinct async contexts without Arc<Mutex> over the object in question and without relying on any kind of internal mutability. It’s mostly aimed at single-threaded executors where internal mutability is unnecessary complication. Still, the BorrowMutex is Send+Sync and can be safely used from any number of threads.

Implementations§

Source§

impl<const M: usize, T: ?Sized> BorrowMutex<M, T>

Source

pub const MAX_BORROWERS: usize = M

Note: must be a power of 2, and must be >= 2

Source

pub const fn new() -> Self

Create a new empty BorrowMutex.

Source

pub fn try_borrow<'g, 'm: 'g>(&'m self) -> BorrowGuardUnarmed<'g, T> ⓘ

Obtain a mutable reference. The returned BorrowGuardUnarmed is a future that resolves after BorrowMutex::lend() is called. Specifically, it resolves to Result<BorrowGuardArmed, Error>.

The error can be:

The borrowers are lended to in FIFO order but they get put to the waiting queue only on their first poll.

A borrow guard which was lended to must be dropped to allow further borrows to happen.

Source

pub fn wait_to_lend<'g, 'm: 'g>(&'m self) -> LendWaiter<'g, T> ⓘ

Wait until BorrowMutex::try_borrow() is called. BorrowMutex::lend() can be called immediately after.

§Note

This can be called concurrently from multiple async contexts but only one wait-er is guaranteed to be awoken.

Source

pub fn lend<'g, 'm: 'g>(&'m self, value: &'g mut T) -> Option<LendGuard<'g, T>>

Lend a mutable reference to the first waiting borrower (FIFO order). The usual pattern is to select! on BorrowMutex::wait_to_lend(), then lend() and await. The await returns after the borrower drops.

This can be also called when there are no borrowers at the time, and the returned LendGuard will effectively wait until the first borrower appears.

This can fail and return None when either:

  • someone else is currently lending
  • someone else is currently terminating the mutex

On successful lend, a LendGuard future is returned which:

  • can be immediately dropped, which makes the whole operation invisible to the borrower - it will keep waiting for another lender
  • or, can be polled, and then has to be polled until completion

The first poll will awake the borrower. Dropping the LendGuard before it resolves (which implies - before the borrowing side drops its guard) will abort the process.

Do not forget the LendGuard with core::mem::forget() or similar, as it may cause Undefined Behavior.

Source

pub async fn terminate(&self) -> Option<()>

Make any borrows requests (pending or to-be-made) return Error::Terminated.

The mutex remains terminated until another BorrowMutex::lend() is called.

This can also fail and return None when either:

  • someone else is currently lending
  • someone else is currently terminating the mutex
§Note

This is an async function as the existing borrowers need to be awoken one by one to drop their guard, which then allows this function to proceed. This only applies to existing borrowers - Any borrows made after the function was polled at least once will immediately return an error on the first poll.

Trait Implementations§

Source§

impl<const M: usize, T: ?Sized> Debug for BorrowMutex<M, T>

Source§

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

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

impl<const M: usize, T: ?Sized> Default for BorrowMutex<M, T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<const M: usize, T: ?Sized + Send> Send for BorrowMutex<M, T>

Source§

impl<const M: usize, T: ?Sized + Send> Sync for BorrowMutex<M, T>

Auto Trait Implementations§

§

impl<const MAX_BORROWERS: usize, T> !Freeze for BorrowMutex<MAX_BORROWERS, T>

§

impl<const MAX_BORROWERS: usize, T> !RefUnwindSafe for BorrowMutex<MAX_BORROWERS, T>

§

impl<const MAX_BORROWERS: usize, T> Unpin for BorrowMutex<MAX_BORROWERS, T>
where UnsafeCell<Option<NonNull<T>>>: Unpin, MPMC<MAX_BORROWERS, BorrowRef>: Unpin, T: ?Sized,

§

impl<const MAX_BORROWERS: usize, T> UnsafeUnpin for BorrowMutex<MAX_BORROWERS, T>
where UnsafeCell<Option<NonNull<T>>>: UnsafeUnpin, MPMC<MAX_BORROWERS, BorrowRef>: UnsafeUnpin, T: ?Sized,

§

impl<const MAX_BORROWERS: usize, T> UnwindSafe for BorrowMutex<MAX_BORROWERS, T>
where UnsafeCell<Option<NonNull<T>>>: UnwindSafe, MPMC<MAX_BORROWERS, BorrowRef>: UnwindSafe, T: ?Sized,

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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.