Added {AsyncSignal, LoadableSignal}::load.

This commit is contained in:
Filipe Rodrigues 2024-12-22 17:48:24 +00:00
parent a12ef68a21
commit a638ff10f1
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
2 changed files with 39 additions and 1 deletions

View File

@ -66,6 +66,20 @@ impl<F: Future<Output = Result<T, E>>, T, E> LoadableSignal<F> {
self.inner.is_suspended.load(atomic::Ordering::Acquire)
}
/// Loads this value asynchronously and returns the value
pub async fn load(&self) -> Result<BorrowRef<'_, T, E>, E>
where
F: Future<Output = Result<T, E>> + 'static,
T: 'static,
E: Clone + 'static,
{
let value = self.inner.signal.load().await;
match &*value {
Ok(_) => Ok(BorrowRef(value)),
Err(err) => Err(err.clone()),
}
}
/// Borrows the inner value, without polling the future.
#[must_use]
pub fn borrow_suspended(&self) -> Loadable<BorrowRef<'_, T, E>, E>

View File

@ -10,7 +10,7 @@ use {
crate::{signal, SignalBorrow, SignalBorrowMut, SignalUpdate, SignalWith, Trigger},
core::{
fmt,
future::Future,
future::{self, Future},
ops::{Deref, DerefMut},
pin::Pin,
task::{self, Poll},
@ -98,6 +98,30 @@ impl<F: Future> AsyncSignal<F> {
Self { inner }
}
/// Loads this value asynchronously and returns the value
pub async fn load(&self) -> BorrowRef<'_, F::Output> {
// Poll until we're loaded
future::poll_fn(|cx| {
// Get the inner future through pin projection.
let mut fut = self.inner.fut.imut_write();
// SAFETY: We guarantee that the future is not moved until it's dropped.
let mut fut = unsafe { Pin::new_unchecked(&mut *fut) };
// Then poll it, and store the value if finished.
let new_value = task::ready!(fut.as_mut().poll(cx));
*self.inner.value.imut_write() = Some(new_value);
Poll::Ready(())
})
.await;
// Then borrow
self.inner.waker.trigger.gather_subscribers();
let borrow = self.inner.value.imut_read();
BorrowRef(borrow)
}
/// Borrows the inner value, without polling the future.
// TODO: Better name that indicates that we don't poll?
#[must_use]