async_once_cell

Struct Lazy

source
pub struct Lazy<T, F> { /* private fields */ }
Expand description

A value which is computed on demand by running a future.

Unlike OnceCell, if a task is cancelled, the initializing future’s execution will be continued by other (concurrent or future) callers of Lazy::get.

use std::sync::Arc;
use async_once_cell::Lazy;

struct Data {
    id: u32,
}

let shared = Arc::pin(Lazy::new(async move {
    Data { id: 4 }
}));

assert_eq!(shared.as_ref().await.id, 4);

Using this type with an async block in a static item requries unstable rust:

#![feature(const_async_blocks)]
#![feature(type_alias_impl_trait)]
mod example {
    use async_once_cell::Lazy;
    use std::future::Future;
    type H = impl Future<Output=i32> + 'static;
    static LAZY: Lazy<i32, H> = Lazy::new(async { 4 });
}

However, it is possile to use if you have a named struct that implements Future:

use async_once_cell::Lazy;
use std::{future::Future, pin::Pin, task};

struct F;
impl Future for F {
    type Output = i32;
    fn poll(self: Pin<&mut Self>, _: &mut task::Context) -> task::Poll<i32> {
        return task::Poll::Ready(4);
    }
}

static LAZY: Lazy<i32, F> = Lazy::new(F);

And this type of struct can still use async syntax in its implementation:

use async_once_cell::Lazy;
use std::{future::Future, pin::Pin, task};

struct F(Option<Pin<Box<dyn Future<Output=i32> + Send>>>);
impl Future for F {
    type Output = i32;
    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> task::Poll<i32> {
        Pin::new(self.0.get_or_insert_with(|| Box::pin(async {
            4
        }))).poll(cx)
    }
}

static LAZY: Lazy<i32, F> = Lazy::new(F(None));

Implementations§

source§

impl<T, F> Lazy<T, F>
where F: Future<Output = T>,

source

pub const fn new(future: F) -> Self

Creates a new lazy value with the given initializing future.

source

pub async fn get(self: Pin<&Self>) -> Pin<&T>

Forces the evaluation of this lazy value and returns a reference to the result.

This is equivalent to calling .await on a pinned reference, but is more explicit.

The Pin::static_ref function may be useful if this is a static value.

source§

impl<T, F> Lazy<T, F>
where F: Future<Output = T> + Unpin,

source

pub async fn get_unpin(&self) -> &T

Forces the evaluation of this lazy value and returns a reference to the result.

This is equivalent to calling .await on a reference, but may be clearer to call explicitly.

Unlike Self::get, this does not require pinning the object.

source§

impl<T, F> Lazy<T, F>

source

pub const fn from_future(future: F) -> Self

Creates a new lazy value with the given initializing future.

This is equivalent to Self::new but with no type bound.

source

pub const fn with_value(value: T) -> Self

Creates an already-initialized lazy value.

source

pub fn try_get(&self) -> Option<&T>

Gets the value without blocking or starting the initialization.

source

pub fn try_get_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>>

Gets the value without blocking or starting the initialization.

This requires mutable access to self, so rust’s aliasing rules prevent any concurrent access and allow violating the usual rules for accessing this cell.

source

pub fn try_get_mut_unpin(&mut self) -> Option<&mut T>

Gets the value without blocking or starting the initialization.

This requires mutable access to self, so rust’s aliasing rules prevent any concurrent access and allow violating the usual rules for accessing this cell.

source

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

Takes ownership of the value if it was set.

Similar to the try_get functions, this returns None if the future has not yet completed, even if the value would be available without blocking.

source

pub fn into_parts(self) -> Result<T, F>

Takes ownership of the value or the initializing future.

source

pub fn replace_and_take(self: Pin<&mut Self>, replacement: Self) -> Option<T>
where T: Unpin,

Takes ownership of the value from a pinned object.

This is equivalent to mem::replace(self, replacement).into_inner() but does not require that F be Unpin like that expression would.

Trait Implementations§

source§

impl<T: Debug, F> Debug for Lazy<T, F>

source§

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

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

impl<T, F> Drop for Lazy<T, F>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<'a, T, F> IntoFuture for &'a Lazy<T, F>
where F: Future<Output = T> + Unpin,

source§

type Output = &'a T

The output that the future will produce on completion.
source§

type IntoFuture = LazyFutureUnpin<'a, T, F>

Which kind of future are we turning this into?
source§

fn into_future(self) -> Self::IntoFuture

Creates a future from a value. Read more
source§

impl<'a, T, F> IntoFuture for Pin<&'a Lazy<T, F>>
where F: Future<Output = T>,

source§

type Output = Pin<&'a T>

The output that the future will produce on completion.
source§

type IntoFuture = LazyFuturePin<'a, T, F>

Which kind of future are we turning this into?
source§

fn into_future(self) -> Self::IntoFuture

Creates a future from a value. Read more
source§

impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for Lazy<T, F>

source§

impl<T: Send, F: Send> Send for Lazy<T, F>

source§

impl<T: Send + Sync, F: Send> Sync for Lazy<T, F>

source§

impl<T: Unpin, F: Unpin> Unpin for Lazy<T, F>

source§

impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for Lazy<T, F>

Auto Trait Implementations§

§

impl<T, F> !Freeze for Lazy<T, F>

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