Skip to main content

RwTaskLock

Struct RwTaskLock 

Source
pub struct RwTaskLock<T, E>
where T: Send + Sync + 'static, E: Send + Sync + 'static + From<RwTaskLockError>,
{ /* private fields */ }
Expand description

A one-time async-initialized, lockable value that yields a read guard after initialization.

RwTaskLock<T, E> allows you to wrap a future or ready value so the computation (e.g., background task, async function) is performed at most once, even if multiple callers invoke .read() concurrently. After the computation, the result is cached. If successful, all future .read() calls yield a read guard on the stored value. If an error occurs, all subsequent calls return the error (error value must be Clone).

§Example

use tokio::time;
use xet_runtime::utils::{RwTaskLock, RwTaskLockError};
#[tokio::main]
async fn main() -> Result<(), RwTaskLockError> {
    let lock = RwTaskLock::from_task(async {
        time::sleep(std::time::Duration::from_millis(50)).await;
        Ok::<_, RwTaskLockError>(vec![1, 2, 3])
    });
    let guard = lock.read().await?;
    assert_eq!(&*guard, &[1, 2, 3]);
    Ok(())
}

Implementations§

Source§

impl<T, E> RwTaskLock<T, E>
where T: Send + Sync + 'static, E: Send + Sync + 'static + From<RwTaskLockError>,

Source

pub fn from_value(val: T) -> Self

From a ready value.

Source

pub fn from_task<Fut>(fut: Fut) -> Self
where Fut: Future<Output = Result<T, E>> + Send + 'static,

From a future yielding Result<T, E>.

Source

pub async fn read(&self) -> Result<RwTaskLockReadGuard<'_, T, E>, E>

Awaitable read: yields a custom read guard or error.

Source

pub async fn update<Fut, Updater>( &self, updater: Updater, ) -> Result<(), RwTaskLockError>
where Updater: FnOnce(T) -> Fut + Send + 'static, Fut: Future<Output = Result<T, E>> + Send + 'static,

Update the current value by applying an async function to it, storing the result as the new value.

  • If the current value is in the Ready state, the function is immediately scheduled as a background task with the current value, and the state becomes Pending until completion.
  • If the value is in the Pending state, this chains the update: when the background task completes, the updater will be called on the resulting value.
  • If the value is in the Error state, returns an error and does nothing.

Returns Ok(()) if the update is scheduled. Errors if the value is already in an error state.

§Example: Chaining updates
use tokio::time;
use xet_runtime::utils::{RwTaskLock, RwTaskLockError};
#[tokio::main]
async fn main() -> Result<(), RwTaskLockError> {
    let lock = RwTaskLock::from_value(10);
    lock.update(|v| async move { Ok::<_, RwTaskLockError>(v * 2) }).await?;
    assert_eq!(*lock.read().await?, 20);

    lock.update(|v| async move { Ok::<_, RwTaskLockError>(v + 5) }).await?;
    assert_eq!(*lock.read().await?, 25);
    Ok(())
}
§Example: Chained with pending state
use std::sync::Arc;

use tokio::time;
use xet_runtime::utils::{RwTaskLock, RwTaskLockError};
#[tokio::main]
async fn main() -> Result<(), RwTaskLockError> {
    let lock = Arc::new(RwTaskLock::from_task(async {
        time::sleep(std::time::Duration::from_millis(10)).await;
        Ok::<_, RwTaskLockError>(10)
    }));
    let lock2 = lock.clone();

    // Chain update while value is still pending
    lock2.update(|v| async move { Ok::<_, RwTaskLockError>(v + 10) }).await?;
    assert_eq!(*lock.read().await?, 20);
    Ok(())
}

Auto Trait Implementations§

§

impl<T, E> !Freeze for RwTaskLock<T, E>

§

impl<T, E> !RefUnwindSafe for RwTaskLock<T, E>

§

impl<T, E> Send for RwTaskLock<T, E>

§

impl<T, E> Sync for RwTaskLock<T, E>

§

impl<T, E> Unpin for RwTaskLock<T, E>
where T: Unpin,

§

impl<T, E> UnsafeUnpin for RwTaskLock<T, E>
where T: UnsafeUnpin,

§

impl<T, E> UnwindSafe for RwTaskLock<T, E>
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> DropFlavorWrapper<T> for T

Source§

type Flavor = MayDrop

The DropFlavor that wraps T into Self
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

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

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. 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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more