Is there any library which provides a data type with the following functionality?
- owns either a
Future
or itsOutput
value - can be asked to await the future if needed, then return a reference to the output
Its API would be like:
pub enum RetainedOutput<F: Future> {
Pending(F),
Ready(F::Output),
}
impl<F: Future> RetainedOutput<F> {
pub fn new(future: F) -> Self {...}
pub async fn get(self: Pin<&mut Self>) -> &F::Output {...}
pub fn try_get(&self) -> Option<&F::Output> {...}
}
This is similar to other library types I’m aware of, but different from all of them:
- It is similar to
MaybeDone
, but has noGone
state. - It is similar to
tokio::sync::OnceCell
, but has no not-yet-initialized state. Shared
can be convinced to behave like this (shared.clone().await
) but would require a clonable output rather than returning references, so you end up with two heap allocations (presuming the output is wrapped inArc
) instead of zero.Shared
is the right answer for accessing such a future-or-output from multiple tasks, though.- It needs no internal synchronization (unlike
OnceCell
andShared
, or an async lazy cell, do), since its state transition is guarded by&mut
access, and therefore can be provided in platform-independent executor-independentno_std
form.
I’ve encountered problems shaped somewhat like this a couple times and it feels like a missing basic abstraction, so I’m wondering if someone has already written it under a name I haven’t thought of.