use futures::prelude::*;
#[derive(Debug)]
struct PromiseBackend<T, E> {
result: Option<Result<T, E>>,
waiting_tasks: Vec<futures::task::Task>,
}
#[derive(Debug, Clone)]
pub struct Promise<T, E> {
backend: std::sync::Arc<std::sync::Mutex<PromiseBackend<T, E>>>,
}
impl<T, E> Promise<T, E> {
pub fn new() -> Promise<T, E> {
Promise {
backend: std::sync::Arc::new(
std::sync::Mutex::new(
PromiseBackend {
result: None,
waiting_tasks: vec![],
}
)
)
}
}
pub fn resolve(&self, result: T) {
let mut backend = self.backend.lock().unwrap();
backend.result = Some(Ok(result));
for task in &backend.waiting_tasks {
task.notify();
}
backend.waiting_tasks.clear();
}
pub fn reject(&self, error: E) {
let mut backend = self.backend.lock().unwrap();
backend.result = Some(Err(error));
for task in &backend.waiting_tasks {
task.notify();
}
backend.waiting_tasks.clear();
}
}
impl <T, E> Future for Promise<T, E> {
type Item = T;
type Error = E;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let mut guard = self.backend.lock().unwrap();
let backend = &mut *guard;
match backend.result {
Some(_) => match backend.result.take().unwrap() {
Ok(result) => std::result::Result::Ok(Async::Ready(result)),
Err(error) => std::result::Result::Err(error),
},
None => {
backend.waiting_tasks.push(futures::task::current());
std::result::Result::Ok(Async::NotReady)
}
}
}
}