engine/promise/src/lib.rs

65 lines
1.8 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
use std::{
ops::Deref,
sync::Mutex,
thread::{self, JoinHandle},
};
enum InternalPromiseState<T: Send + Clone> {
Loading(Option<JoinHandle<Result<T, anyhow::Error>>>),
Result(Result<T, anyhow::Error>),
}
impl<T: Send + Clone> InternalPromiseState<T> {
fn loading(&mut self) -> Option<JoinHandle<anyhow::Result<T>>> {
match self {
Self::Loading(handle) => handle.take(),
_ => None,
}
}
}
pub struct Promise<T: Send + Clone> {
internal: Mutex<InternalPromiseState<T>>,
}
impl<T: Send + Clone> Promise<T> {
pub fn new<F>(f: F) -> Promise<T>
where
F: Fn() -> anyhow::Result<T> + 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!(),
}
}
}