Skip to main content

Nutex

Struct Nutex 

Source
pub struct Nutex<T: Sized> { /* private fields */ }
Expand description

A nullable Mutex-like type based on tokio::sync::Mutex implementation.

Nutex stands for NUllable muTEX and it gives you convenience to work with Optional values, such as connection that cannot be set at the time when they was created: you no more need to unwrap the value all the time in functions that cannot be accessed without Mutex<Option<T>> value defining.

Note that locking Nutex requires to be certain that value is not None and if you are not sure that function cannot be accessed without value defining use Nutex::safe_lock or Nutex::safe_blocking_lock instead.

Otherwise if value is None, Nutex::locking will lead you to panic.


§Usage Examples

For example, you created an app and you want to access and process the user client data stored in mutex in the some function that may be called only if user is logged in.

With using the standard Tokio mutex you should unwrap the value all the time:

pub struct AppState {
    pub client: Mutex<Option<Client>>,
    // ...
}

#[tauri::command]
pub async fn send_message(
    state: State<'_, AppState>,
    message: String,
    to: RecId
) -> Result<(), SendError> {
    // ? You need to do THIS:
    state
        .client
        .lock()
        .await
        .expect("User must be logged in, blah, blah, blah...")
        .user_id()
        .expect("User must be logged in, blah blah blah...")
        .process()
        .yet_another_process()
        .et_cetera();
    // ...
    Ok(())
}

#[tauri::command]
pub async fn register(
    state: State<'_, AppState>,
    auth_data: AuthData,
) -> Result<(), ErrorResponse> {
    // ? And THIS...
    state.client.lock().await = Some(
        Client::builder()
            .register(auth_data)
            .build()
            .await?
            .map_err(/* ... */)?;
    )
    // ...
    Ok(())
}

Double checking. Double headache. But Nutex gives you this:

pub struct AppState {
    pub client: Nutex<Client>,
    // ...
}

#[tauri::command]
pub async fn send_message(
    state: State<'_, AppState>,
    message: String,
    to: RecId
) -> Result<(), SendError> {
    state
        .client
        .lock()
        .await
        .user_id()
        .expect("User must be logged in, blah blah blah...")
        .process();
    // ...
    Ok(())
}

#[tauri::command]
pub async fn register(
    state: State<'_, AppState>,
    auth_data: AuthData,
) -> Result<(), ErrorResponse> {
    state.client.set(
        Client::builder()
            .register(auth_data)
            .build()
            .await?
            .map_err(/* ... */)?;
            // ...
    ).await;

    Ok(())
}

It simplifies the code a lot because Mutexes frequently used with values that cannot be known at the time when they are created.

§Examples

If you certainly know that value is not None, then you can just lock the Nutex and access the value:

let nutex = Nutex::from(String::from("foo"));
*nutex.lock().await = String::from("bar");
assert_eq!(String::from("bar"), *nutex.lock().await);

But if you’re not sure that it’s not None, prefer using Nutex::safe_lock:

if let Some(mut guard) = nutex.safe_lock().await {
    *guard = String::from("foo");
}

Other documentation about Nutex may be found in the tokio::sync::Mutex docs: Nutex is just a wrapper for this anyway.

Implementations§

Source§

impl<'a, T: Sized> Nutex<T>

Source

pub fn new() -> Self

Creates a new Nutex that contains None. Value may be set later by Nutex::set or dereferencing Nutex::safe_lock.

Source

pub async fn get(&self) -> T
where T: Clone + Sized,

Asynchronously gets the value snapshot. Because of result value is clone and not the immutable reference, it’s not reactive and cannot be observed later.


§Panics
  • Panics if Nutex value is not set. If you are not sure that calling function cannot be called without setting the value, use Nutex::safe_get instead.
Source

pub fn blocking_get(&self) -> T
where T: Clone + Sized,

Same as Nutex::get, but blocks the code execution until value is get.

Source

pub async fn safe_get(&self) -> Option<T>
where T: Clone + Sized,

“Safe” edition of the original Nutex::get method.

Note that “safe” doesn’t mean that original method usage is discouraged: this method may be used if you are not sure that value exist.

Although if more than half of your code contains this method, think about the original tokio::sync::Mutex instead of Nutex.

Source

pub fn safe_blocking_get(&self) -> Option<T>
where T: Clone + Sized,

Same as Nutex::safe_get, but blocks the code execution until value is get.

Source

pub async fn set(&self, val: T)

Sets the value in the Nutex, replacing inner None to the Some(value).

Note that this method does nothing if value is already set: if you need to mutate the value that Nutex contains, use Nutex::lock or Nutex::blocking_lock instead.

Source

pub fn blocking_set(&self, val: T)

Same as Nutex::set, but blocks the code execution until value is set.

Source

pub async fn clear(&self)

Sets inner value of the Nutex as None.

Source

pub fn blocking_clear(&self)

Same as Nutex::clear, but blocks the code execution until value is cleared.

Source

pub async fn lock(&'a self) -> NutexGuard<'a, T>

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

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


§Panics
  • Panics if Nutex value is not set. If you are not sure that calling function cannot be called without setting the value, use Nutex::safe_lock instead.
Source

pub async fn lock_expect(&'a self, msg: &str) -> NutexGuard<'a, T>

Same as Nutex::lock, but if value is not set, it panics with a custom message.

Useful if panic impossibility reason is opaque and you should explain why panic is impossible.

Source

pub fn blocking_lock(&'a self) -> NutexGuard<'a, T>

Same as Nutex::lock, but blocks the code execution until Nutex is locked.

Source

pub fn blocking_lock_expect(&'a self, msg: &str) -> NutexGuard<'a, T>

Same as Nutex::lock_expect, but blocks the code execution until Nutex is locked.

Source

pub async fn safe_lock(&'a self) -> Option<NutexGuard<'a, T>>

“Safe” edition of the original Nutex::lock method.

Note that “safe” doesn’t mean that original method usage is discouraged: this method may be used if you are not sure that value exist.

Although if more than half of your code contains this method, think about the original tokio::sync::Mutex instead of Nutex.

Source

pub fn safe_blocking_lock(&'a self) -> Option<NutexGuard<'a, T>>

Same as Nutex::safe_lock, but blocks the code execution until Nutex is locked.

Source

pub fn try_lock(&'a self) -> Result<NutexGuard<'a, T>, TryLockError>

Synchronous function to lock Nutex.

Returns [tokio::sync::mutex::TryLockError] if Nutex is locked currently.

Source

pub async fn lock_then<U, F: AsyncFnOnce(NutexGuard<'a, T>) -> U>( &'a self, f: F, ) -> Option<U>

Locks the Nutex and transforms the type inside to other.

This method is lazily evaluated that means closure won’t be executed if Nutex contains None.

Source

pub fn blocking_lock_then<U, F: FnOnce(NutexGuard<'a, T>) -> U>( &'a self, f: F, ) -> Option<U>

Same as Nutex::lock_then, but if closure should be executed it’ll block the code execution until its evaluation is done.

This method is also lazily evaluated that means closure won’t be executed if Nutex contains None.

Source

pub fn is_some(&self) -> bool

Atomic checker that inner value is not None.

Note that this method shouldn’t be used to check that Nutex should be locked because it’s not asynchronous that means that you may face to the race condition.

Consider using Nutex::safe_lock or Nutex::safe_blocking_lock with if let Some(val) statement, or Nutex::lock_then/Nutex::blocking_lock_then to evaluate the statement lazily.

Source

pub fn is_none(&self) -> bool

Atomic checker that inner value is None.

Source

pub fn into_inner(self) -> Option<T>

Consumes the Nutex, returning the underlying data.

Trait Implementations§

Source§

impl<T: Debug + Sized> Debug for Nutex<T>

Source§

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

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

impl<T: Sized> Default for Nutex<T>

Source§

fn default() -> Self

Creates default value of Nutex. Shorthand of this expression is Nutex::new.

Inner value of Nutex is None by default.

Source§

impl<T: Sized> From<T> for Nutex<T>

Source§

fn from(value: T) -> Self

Creates Nutex with the inner value from the argument.

Auto Trait Implementations§

§

impl<T> !Freeze for Nutex<T>

§

impl<T> !RefUnwindSafe for Nutex<T>

§

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

§

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

§

impl<T> Unpin for Nutex<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for Nutex<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for Nutex<T>
where T: UnwindSafe,

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<!> for T

Source§

fn from(t: !) -> T

Converts to this type from the input type.
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 = 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.