init-once 0.6.1

Concurrent, non-blocking lazy initialization of values.
Documentation
use std::fmt::Debug;
use std::sync::Arc;

use init_once::InitOnce;
use tokio::time;

struct AnnounceDrop<T: Debug> {
    value: T,
}

#[tokio::main]
async fn main() {
    let init_once = Arc::new(InitOnce::new());

    let threads: Vec<_> = (0..10)
        .map(|i| {
            let init_once = Arc::clone(&init_once);
            tokio::spawn(async move {
                let worker_sleep_dur = time::Duration::from_secs(i);
                println!("I am thread {i}, sleeping for {worker_sleep_dur:?}");

                time::sleep(worker_sleep_dur).await;

                let maybe_value = init_once
                    .try_init_async(async {
                        time::sleep(time::Duration::from_secs(5)).await;
                        println!("Took a second but we out here");
                        AnnounceDrop {
                            value: format!("I am thread {i}, blazing 420"),
                        }
                    })
                    .await;

                if let Some(AnnounceDrop { value }) = maybe_value {
                    println!("Read {value:?} from {i}");
                } else {
                    println!("Thread {i} couldn't read value");
                }
            })
        })
        .collect();

    for handle in threads {
        handle.await.unwrap();
    }
}

impl<T: Debug> Drop for AnnounceDrop<T> {
    fn drop(&mut self) {
        println!("Dropping value: {:?}", self.value);
    }
}