use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll, ready};
pub struct Handle<T> {
pub value: Option<T>,
}
impl<T> Default for Handle<T> {
fn default() -> Self {
Self { value: None }
}
}
pub struct Task<'a, F: Future> {
pub name: Option<&'a str>,
pub future: F,
handle: Option<&'a mut Handle<F::Output>>,
}
impl<'a, F: Future> Task<'a, F> {
const fn new_impl(name: Option<&'a str>, future: F) -> Self {
Self {
name,
future,
handle: None,
}
}
pub const fn new(name: &'a str, future: F) -> Self {
Self::new_impl(Some(name), future)
}
pub const fn new_nameless(future: F) -> Self {
Self::new_impl(None, future)
}
#[must_use]
pub fn create_handle(&self) -> Handle<F::Output> {
Handle::default()
}
pub(crate) fn link_handle(&mut self, handle: &'a mut Handle<F::Output>) {
self.handle = Some(handle);
}
}
impl<T: Future> Future for Task<'_, T> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = unsafe { self.get_unchecked_mut() };
let mut future = unsafe { Pin::new_unchecked(&mut this.future) };
let res = ready!(future.as_mut().poll(cx));
if let Some(handle) = this.handle.as_mut() {
handle.value = Some(res);
}
Poll::Ready(())
}
}
pub(crate) trait TaskName {
fn name(&self) -> Option<&str>;
}
impl<T: Future> TaskName for Task<'_, T> {
fn name(&self) -> Option<&str> {
self.name
}
}
pub(crate) trait TaskFuture: Future<Output = ()> + TaskName {}
impl<T: Future> TaskFuture for Task<'_, T> {}