use futures::future::{BoxFuture, FutureExt, Shared};
pub struct AsyncLazy<O: 'static + Clone + Send + Sync> {
fut: Shared<BoxFuture<'static, O>>,
}
impl<O: 'static + Clone + Send + Sync> AsyncLazy<O> {
pub fn new<F>(f: F) -> Self
where
F: 'static + std::future::Future<Output = O> + Send,
{
Self {
fut: f.boxed().shared(),
}
}
pub fn get(&self) -> impl std::future::Future<Output = O> + 'static {
self.fut.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
#[tokio::test(flavor = "multi_thread")]
async fn async_lazy() {
let s = AsyncLazy::new(async move {
tokio::time::sleep(std::time::Duration::from_millis(20)).await;
Arc::new(42)
});
assert_eq!(
vec![Arc::new(42), Arc::new(42)],
futures::future::join_all(vec![s.get(), s.get()]).await
);
assert_eq!(42, *s.get().await);
assert_eq!(42, *s.get().await);
}
}