use std::future::Future; use std::pin::Pin; use std::sync::{Arc, RwLock}; use std::task::{Context, Poll, Waker}; type Waiter = Box; pub struct Promise { inner: Arc>>, waiters: Arc>>>, } pub struct Complete { inner: Arc>>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Cancelled; struct Inner { value: Option>, waker: Option, } pub fn promise() -> (Complete, Promise) { let inner = Arc::new(RwLock::new(Inner { value: None, waker: None, })); let promise = Promise { inner: inner.clone(), waiters: Arc::new(RwLock::new(Vec::new())), }; let complete = Complete { inner }; (complete, promise) } impl Complete { pub fn fulfill(&self, val: T) { let mut inner = self.inner.write().unwrap(); inner.value = Some(Arc::new(val)); if let Some(waker) = inner.waker.take() { waker.wake() } } } impl Complete> { pub fn cancel(&mut self) { self.fulfill(Err(Cancelled)) } } impl Complete> { pub fn ok(&mut self, val: T) { self.fulfill(Ok(val)) } pub fn err(&mut self, e: E) { self.fulfill(Err(e)) } } impl Promise { pub fn on_fulfill(&mut self, f: F) { let mut waiters = self.waiters.write().unwrap(); waiters.push(Box::new(f)); } } impl Promise> { pub fn on_cancel(&mut self, f: F) { self.on_err(move |env, _| f(env)) } } impl Promise> { pub fn on_ok(&mut self, f: F) { self.on_fulfill(move |env, r| { if let Ok(val) = r { f(env, val) } }) } pub fn on_err(&mut self, f: F) { self.on_fulfill(move |env, r| { if let Err(e) = r { f(env, e) } }) } } pub trait Give { fn give(&self, env: &mut Env) -> bool; } impl Give for Promise { fn give(&self, env: &mut Env) -> bool { let inner = self.inner.read().unwrap(); if let Some(value) = &inner.value { let mut waiters = self.waiters.write().unwrap(); for waiter in waiters.iter() { waiter(env, value); } waiters.clear(); true } else { false } } } impl Clone for Promise { fn clone(&self) -> Self { Promise { inner: self.inner.clone(), waiters: self.waiters.clone(), } } } impl> Give for &P { fn give(&self, env: &mut Env) -> bool { (*self).give(env) } } impl Future for Promise { type Output = Arc; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let mut inner = self.inner.write().unwrap(); match inner.value { Some(ref v) => Poll::Ready(v.clone()), None => { inner.waker = Some(cx.waker().clone()); Poll::Pending } } } } pub struct Promises<'a, Env> { ps: Vec + 'a>>, } impl<'a, Env> Promises<'a, Env> { pub fn new() -> Self { Promises { ps: Vec::new() } } pub fn push(&mut self, p: Box + 'a>) { self.ps.push(p); } pub fn give_all(&mut self, env: &mut Env) { self.ps.retain(|p| !p.give(env)); } }