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>,
impl<T, F> Lazy<T, F>where
F: Future<Output = T>,
source§impl<T, F> Lazy<T, F>
impl<T, F> Lazy<T, F>
sourcepub const fn from_future(future: F) -> Self
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.
sourcepub const fn with_value(value: T) -> Self
pub const fn with_value(value: T) -> Self
Creates an already-initialized lazy value.
sourcepub fn try_get(&self) -> Option<&T>
pub fn try_get(&self) -> Option<&T>
Gets the value without blocking or starting the initialization.
sourcepub fn try_get_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>>
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.
sourcepub fn try_get_mut_unpin(&mut self) -> Option<&mut T>
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.
sourcepub fn into_inner(self) -> Option<T>
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.
sourcepub fn into_parts(self) -> Result<T, F>
pub fn into_parts(self) -> Result<T, F>
Takes ownership of the value or the initializing future.
sourcepub fn replace_and_take(self: Pin<&mut Self>, replacement: Self) -> Option<T>where
T: Unpin,
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.