Skip to main content

ArcAsyncMutex

Struct ArcAsyncMutex 

Source
pub struct ArcAsyncMutex<T> { /* private fields */ }
Expand description

Asynchronous Mutex Wrapper

Provides an encapsulation of asynchronous mutex for protecting shared data in asynchronous environments. Supports safe access and modification of shared data across multiple asynchronous tasks.

§Features

  • Asynchronously acquires locks, does not block threads
  • Supports trying to acquire locks (non-blocking)
  • Thread-safe, supports multi-threaded sharing
  • Automatic lock management through RAII ensures proper lock release
  • Implements Deref and AsRef to expose the underlying tokio::sync::Mutex API when guard-based access is needed

§Usage Example

use qubit_lock::lock::{ArcAsyncMutex, AsyncLock};

let rt = tokio::runtime::Builder::new_current_thread()
    .enable_all()
    .build()
    .unwrap();
rt.block_on(async {
    let counter = ArcAsyncMutex::new(0);

    // Asynchronously modify data
    counter.write(|c| {
        *c += 1;
        println!("Counter: {}", *c);
    }).await;

    // Try to acquire lock
    if let Ok(value) = counter.try_read(|c| *c) {
        println!("Current value: {}", value);
    }
});

Implementations§

Source§

impl<T> ArcAsyncMutex<T>

Source

pub fn new(data: T) -> Self

Creates a new asynchronous mutex lock

§Arguments
  • data - The data to be protected
§Returns

Returns a new ArcAsyncMutex instance

§Example
use qubit_lock::lock::ArcAsyncMutex;

let lock = ArcAsyncMutex::new(42);

Methods from Deref<Target = AsyncMutex<T>>§

Source

pub async fn lock(&self) -> MutexGuard<'_, T>

Locks this mutex, causing the current task to yield until the lock has been acquired. When the lock has been acquired, function returns a MutexGuard.

If the mutex is available to be acquired immediately, then this call will typically not yield to the runtime. However, this is not guaranteed under all circumstances.

§Cancel safety

This method uses a queue to fairly distribute locks in the order they were requested. Cancelling a call to lock makes you lose your place in the queue.

§Examples
use tokio::sync::Mutex;

let mutex = Mutex::new(1);

let mut n = mutex.lock().await;
*n = 2;
Source

pub fn blocking_lock(&self) -> MutexGuard<'_, T>

Blockingly locks this Mutex. When the lock has been acquired, function returns a MutexGuard.

This method is intended for use cases where you need to use this mutex in asynchronous code as well as in synchronous code.

§Panics

This function panics if called within an asynchronous execution context.

  • If you find yourself in an asynchronous execution context and needing to call some (synchronous) function which performs one of these blocking_ operations, then consider wrapping that call inside [spawn_blocking()][crate::runtime::Handle::spawn_blocking] (or [block_in_place()][crate::task::block_in_place]).
§Examples
use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let mutex =  Arc::new(Mutex::new(1));
    let lock = mutex.lock().await;

    let mutex1 = Arc::clone(&mutex);
    let blocking_task = tokio::task::spawn_blocking(move || {
        // This shall block until the `lock` is released.
        let mut n = mutex1.blocking_lock();
        *n = 2;
    });

    assert_eq!(*lock, 1);
    // Release the lock.
    drop(lock);

    // Await the completion of the blocking task.
    blocking_task.await.unwrap();

    // Assert uncontended.
    let n = mutex.try_lock().unwrap();
    assert_eq!(*n, 2);
}
Source

pub fn blocking_lock_owned(self: Arc<Mutex<T>>) -> OwnedMutexGuard<T>

Blockingly locks this Mutex. When the lock has been acquired, function returns an OwnedMutexGuard.

This method is identical to Mutex::blocking_lock, except that the returned guard references the Mutex with an Arc rather than by borrowing it. Therefore, the Mutex must be wrapped in an Arc to call this method, and the guard will live for the 'static lifetime, as it keeps the Mutex alive by holding an Arc.

§Panics

This function panics if called within an asynchronous execution context.

  • If you find yourself in an asynchronous execution context and needing to call some (synchronous) function which performs one of these blocking_ operations, then consider wrapping that call inside [spawn_blocking()][crate::runtime::Handle::spawn_blocking] (or [block_in_place()][crate::task::block_in_place]).
§Examples
use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let mutex =  Arc::new(Mutex::new(1));
    let lock = mutex.lock().await;

    let mutex1 = Arc::clone(&mutex);
    let blocking_task = tokio::task::spawn_blocking(move || {
        // This shall block until the `lock` is released.
        let mut n = mutex1.blocking_lock_owned();
        *n = 2;
    });

    assert_eq!(*lock, 1);
    // Release the lock.
    drop(lock);

    // Await the completion of the blocking task.
    blocking_task.await.unwrap();

    // Assert uncontended.
    let n = mutex.try_lock().unwrap();
    assert_eq!(*n, 2);
}
Source

pub async fn lock_owned(self: Arc<Mutex<T>>) -> OwnedMutexGuard<T>

Locks this mutex, causing the current task to yield until the lock has been acquired. When the lock has been acquired, this returns an OwnedMutexGuard.

If the mutex is available to be acquired immediately, then this call will typically not yield to the runtime. However, this is not guaranteed under all circumstances.

This method is identical to Mutex::lock, except that the returned guard references the Mutex with an Arc rather than by borrowing it. Therefore, the Mutex must be wrapped in an Arc to call this method, and the guard will live for the 'static lifetime, as it keeps the Mutex alive by holding an Arc.

§Cancel safety

This method uses a queue to fairly distribute locks in the order they were requested. Cancelling a call to lock_owned makes you lose your place in the queue.

§Examples
use tokio::sync::Mutex;
use std::sync::Arc;

let mutex = Arc::new(Mutex::new(1));

let mut n = mutex.clone().lock_owned().await;
*n = 2;
Source

pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError>

Attempts to acquire the lock, and returns TryLockError if the lock is currently held somewhere else.

§Examples
use tokio::sync::Mutex;

let mutex = Mutex::new(1);

let n = mutex.try_lock()?;
assert_eq!(*n, 1);
Source

pub fn try_lock_owned( self: Arc<Mutex<T>>, ) -> Result<OwnedMutexGuard<T>, TryLockError>

Attempts to acquire the lock, and returns TryLockError if the lock is currently held somewhere else.

This method is identical to Mutex::try_lock, except that the returned guard references the Mutex with an Arc rather than by borrowing it. Therefore, the Mutex must be wrapped in an Arc to call this method, and the guard will live for the 'static lifetime, as it keeps the Mutex alive by holding an Arc.

§Examples
use tokio::sync::Mutex;
use std::sync::Arc;

let mutex = Arc::new(Mutex::new(1));

let n = mutex.clone().try_lock_owned()?;
assert_eq!(*n, 1);

Trait Implementations§

Source§

impl<T> AsRef<Mutex<T>> for ArcAsyncMutex<T>

Source§

fn as_ref(&self) -> &AsyncMutex<T>

Returns a reference to the underlying Tokio mutex.

This is useful when callers need guard-based APIs such as AsyncMutex::lock or AsyncMutex::try_lock instead of the closure-based AsyncLock methods.

Source§

impl<T> AsyncLock<T> for ArcAsyncMutex<T>
where T: Send,

Source§

async fn read<R, F>(&self, f: F) -> R
where F: FnOnce(&T) -> R + Send, R: Send,

Acquires the mutex and executes a read-only operation.

§Arguments
  • f - Closure receiving immutable access to the protected value.
§Returns

A future resolving to the closure result.

Source§

async fn write<R, F>(&self, f: F) -> R
where F: FnOnce(&mut T) -> R + Send, R: Send,

Acquires the mutex and executes a mutable operation.

§Arguments
  • f - Closure receiving mutable access to the protected value.
§Returns

A future resolving to the closure result.

Source§

fn try_read<R, F>(&self, f: F) -> Result<R, TryLockError>
where F: FnOnce(&T) -> R,

Attempts to acquire the mutex for a read-only operation without waiting.

§Arguments
  • f - Closure receiving immutable access when the mutex is available.
§Returns

Ok(result) if the mutex was acquired, or TryLockError::WouldBlock if it was busy.

Source§

fn try_write<R, F>(&self, f: F) -> Result<R, TryLockError>
where F: FnOnce(&mut T) -> R,

Attempts to acquire the mutex for a mutable operation without waiting.

§Arguments
  • f - Closure receiving mutable access when the mutex is available.
§Returns

Ok(result) if the mutex was acquired, or TryLockError::WouldBlock if it was busy.

Source§

impl<T> Clone for ArcAsyncMutex<T>

Source§

fn clone(&self) -> Self

Clones the asynchronous mutex

Creates a new ArcAsyncMutex instance that shares the same underlying lock with the original instance. This allows multiple tasks to hold references to the same lock simultaneously.

§Returns

A new handle sharing the same underlying async mutex and protected value.

1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Deref for ArcAsyncMutex<T>

Source§

fn deref(&self) -> &Self::Target

Dereferences this wrapper to the underlying Tokio mutex.

Method-call dereferencing lets callers use native async mutex APIs directly, while the wrapper continues to provide the AsyncLock trait methods.

Source§

type Target = Mutex<T>

The resulting type after dereferencing.

Auto Trait Implementations§

§

impl<T> Freeze for ArcAsyncMutex<T>

§

impl<T> !RefUnwindSafe for ArcAsyncMutex<T>

§

impl<T> Send for ArcAsyncMutex<T>
where T: Send,

§

impl<T> Sync for ArcAsyncMutex<T>
where T: Send,

§

impl<T> Unpin for ArcAsyncMutex<T>

§

impl<T> UnsafeUnpin for ArcAsyncMutex<T>

§

impl<T> !UnwindSafe for ArcAsyncMutex<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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

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

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.