/* * lazy_rc - Rc and Arc with *lazy* initialization * This is free and unencumbered software released into the public domain. */ use std::fmt::Debug; use std::io::Result; use std::rc::Rc; use std::thread; use std::time::Duration; use chrono::{Timelike, Utc}; use rand::random; use lazy_rc::LazyRc; thread_local! { static INSTANCE: LazyRc = LazyRc::empty(); } #[derive(Debug)] struct MyStruct { _value: u32, } impl MyStruct { fn new() -> Result { // Simulate a lengthy computation! thread::sleep(Duration::from_secs(15)); Ok(Self { _value: random() }) } /// Returns a thread-local instance that will be created on first access. /// If the initialization function fails, then an Error will be returned. pub fn instance() -> Result> { INSTANCE.with(|instance| instance.or_try_init_with(Self::new)) } } fn main() { let mut threads = Vec::with_capacity(3); for _n in 0..3 { threads.push(thread::spawn(|| { print_with_timestamp("Start!"); print_with_timestamp(MyStruct::instance()); print_with_timestamp(MyStruct::instance()); print_with_timestamp(MyStruct::instance()); })); } threads.drain(..) .for_each(|t| t.join().unwrap()); } fn print_with_timestamp(value: T) where T: Debug, { let now = Utc::now(); println!( "[{:02}:{:02}:{:02}.{:03}] [{:?}] {:?}", now.hour(), now.minute(), now.second(), now.nanosecond() / 1000000, thread::current().id(), value ); }