init-once 0.6.1

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

use init_once::InitOnce;

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

fn main() {
    let init_once = Arc::new(InitOnce::new());

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

                thread::sleep(worker_sleep_dur);

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

                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.join().unwrap();
    }
}

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