use super::{sched_from_waker, task_from_waker, TaskRef};
use crate::event::{Scheduler, Timer};
use core::future::Future;
use core::mem::MaybeUninit;
use core::pin::Pin;
use core::task::{Context, Poll};
use core::time::Duration;
use hioff::container_of_mut;
pub struct SendFuture<T: Future> {
future: T,
}
unsafe impl<T: Future> Send for SendFuture<T> {}
impl<T: Future> SendFuture<T> {
pub unsafe fn new(future: T) -> Self {
Self { future }
}
}
impl<T: Future> Future for SendFuture<T> {
type Output = T::Output;
#[inline(always)]
fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
Future::poll(
unsafe { Pin::new_unchecked(&mut Pin::into_inner_unchecked(self).future) },
ctx,
)
}
}
pub(crate) struct FnOnceFuture<F, R>(MaybeUninit<F>)
where
F: FnOnce() -> R;
impl<F, R> FnOnceFuture<F, R>
where
F: FnOnce() -> R,
{
pub(crate) fn new(f: F) -> Self {
Self(MaybeUninit::new(f))
}
}
impl<F, R> Future for FnOnceFuture<F, R>
where
F: FnOnce() -> R,
{
type Output = R;
fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll<Self::Output> {
let this = unsafe { &mut Pin::into_inner_unchecked(self) };
Poll::Ready(unsafe { this.0.assume_init_read() }())
}
}
pub(crate) struct Sleep {
timer: Timer,
task: Option<TaskRef>,
timeout: Duration,
status: u32,
}
impl Unpin for Sleep {}
unsafe impl Send for Sleep {}
impl Sleep {
pub(crate) fn new(timeout: Duration) -> Self {
Self {
timer: Timer::new(Self::timer_handle),
task: None,
timeout,
status: 0,
}
}
fn timer_handle(timer: &Timer, sched: &mut Scheduler) {
let this = unsafe { container_of_mut!(timer, Self, timer) };
let task = this.task.take().unwrap();
task.sched_waked(sched);
this.status = 2;
}
}
impl Future for Sleep {
type Output = ();
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
match self.status {
0 => {},
1 => return Poll::Pending,
2 => return Poll::Ready(()),
_ => unreachable!(),
}
let mut task = unsafe { task_from_waker(ctx.waker()).as_ref() }.task_ref();
task.status.inc_wake();
task.status.set_yield();
self.task = Some(task);
let sched = unsafe { sched_from_waker(ctx.waker()).as_mut() };
sched.set_timer(&self.timer, self.timeout.as_micros() as u32);
self.status = 1;
Poll::Pending
}
}
pub(crate) struct Yield(bool);
impl Yield {
pub fn new() -> Self {
Self(false)
}
}
impl Future for Yield {
type Output = ();
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 {
return Poll::Ready(());
}
let task = unsafe { task_from_waker(ctx.waker()).as_mut() };
task.status.inc_wake();
task.status.set_yield();
let sched = unsafe { sched_from_waker(ctx.waker()).as_mut() };
task.task_ref().sched_waked(sched);
self.0 = true;
Poll::Pending
}
}
pub(crate) struct Delay<T: Future> {
future: T,
sleep: Sleep,
}
impl<T: Future> Unpin for Delay<T> {}
unsafe impl<T: Future + Send> Send for Delay<T> {}
impl<T: Future> Delay<T> {
pub fn new(delay: Duration, future: T) -> Self {
Self {
sleep: Sleep::new(delay),
future,
}
}
}
impl<T: Future> Future for Delay<T> {
type Output = T::Output;
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
let sleep = unsafe { Pin::new_unchecked(&mut self.sleep) };
if Future::poll(sleep, ctx) == Poll::Ready(()) {
let pinned = unsafe { Pin::new_unchecked(&mut self.future) };
return Future::poll(pinned, ctx);
}
Poll::Pending
}
}
pub(crate) struct Deadline<T: Future> {
future: T,
timeout: Duration,
}
impl<T: Future> Unpin for Deadline<T> {}
unsafe impl<T: Future + Send> Send for Deadline<T> {}
impl<T: Future> Deadline<T> {
pub fn new(timeout: Duration, future: T) -> Self {
Self { future, timeout }
}
}
impl<T: Future> Future for Deadline<T> {
type Output = T::Output;
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
let tm = crate::time::now();
if self.timeout >= tm {
let pinned = unsafe { Pin::new_unchecked(&mut self.future) };
return Future::poll(pinned, ctx);
}
let task = unsafe { task_from_waker(ctx.waker()).as_mut() };
task.poll_deadline();
task.status.inc_wake();
Poll::Pending
}
}