I'm working on some code in which I want to wrap the results of some polling operations into nice async wrappers. For that, I've spun up a simple struct that looks kind of like this:
enum FutureValueInner<T> {
Empty,
Waker(Waker),
Value(T),
}
struct FutureValue<T>(Arc<Mutex<FutureValueInner<T>>>);
impl<T> FutureValue<T> {
fn set_value(&self, value: T) {
let mut inner = self.0.lock().unwrap();
if let FutureValueInner::Waker(waker) = &*inner {
waker.wake_by_ref();
}
*inner = FutureValueInner::Value(value);
}
}
impl<T> Future for FutureValue<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
let mut inner = self.0.lock().unwrap();
let old_inner = std::mem::replace(&mut *inner, FutureValueInner::Empty);
match old_inner {
FutureValueInner::Empty | FutureValueInner::Waker(_) => {
*inner = FutureValueInner::Waker(ctx.waker().clone());
Poll::Pending
}
FutureValueInner::Value(value) => Poll::Ready(value),
}
}
}
The code is simplified for brevity, but not by much. Does a crate with primitives like this exist? Say simple, ready-made future implementations that solve problems like this and are well-tested.