use std::{ ops::Deref, sync::Mutex, thread::{self, JoinHandle}, }; enum InternalPromiseState { Loading(Option>>), Result(Result), } impl InternalPromiseState { fn loading(&mut self) -> Option>> { match self { Self::Loading(handle) => handle.take(), _ => None, } } } pub struct Promise { internal: Mutex>, } impl Promise { pub fn new(f: F) -> Promise where F: Fn() -> anyhow::Result + Send + 'static, T: 'static, { let thread = thread::spawn(f); Promise { internal: Mutex::new(InternalPromiseState::Loading(Some(thread))), } } pub fn get(&self) -> T { let mut internal = self.internal.lock().expect("promise lock is poisoned"); if let Some(handle) = internal.loading() { let result = handle.join(); match result { Ok(result) => match result { Ok(t) => *internal = InternalPromiseState::Result(Ok(t)), Err(err) => *internal = InternalPromiseState::Result(Err(err)), }, Err(err) => { println!("Promise Thread Join Error: {:?}", err); *internal = InternalPromiseState::Result(Err(anyhow::Error::msg( "Failed joining thread", ))) } } } match internal.deref() { InternalPromiseState::Result(t) => t.as_ref().expect("result error").clone(), InternalPromiseState::Loading(_) => unreachable!(), } } }