1use core::{pin::Pin, task::Poll};
2
3use crate::{
4 abi,
5 context::{self, PollCall, PollResult},
6 task::storage::slots::{self, Action},
7};
8
9#[pin_project::pin_project]
11#[repr(transparent)]
12#[must_use = "a task does nothing unless it is driven"]
13pub struct Task<F> {
14 #[pin]
15 state: slots::raw::Entry<F, ()>,
16}
17
18impl<F> Task<F> {
19 pub const fn new(fiber: F) -> Self {
20 Self {
21 state: slots::raw::Entry::live(fiber),
22 }
23 }
24 pub(crate) fn poll_with<'d>(
25 self: Pin<&mut Self>,
26 poll: impl FnOnce(Pin<&mut F>) -> PollResult<F::Output>,
27 ) -> PollResult<F::Output>
28 where
29 F: abi::Fiber<'d>,
30 {
31 match self
32 .project()
33 .state
34 .visit((), |fiber, ()| match poll(fiber) {
35 result @ PollResult::Polled(Poll::Ready(_)) => Action::Vacate(result),
36 result => Action::Keep(result),
37 }) {
38 slots::Phase::Live(result) => result,
39 slots::Phase::Vacant(()) | slots::Phase::Done(()) => PollResult::Polled(Poll::Pending),
40 }
41 }
42}
43
44impl<'d, F: abi::Fiber<'d>> abi::Fiber<'d> for Task<F> {
45 type Output = F::Output;
46 fn poll(call: PollCall<'_, '_, 'd, Self>) -> Poll<Self::Output> {
47 let (this, context) = call.into_parts();
48 match this.poll_with(|fiber| {
49 PollResult::Polled(unsafe { context::raw::Live::new(fiber).delegate(context) })
51 }) {
52 PollResult::Polled(poll) => poll,
53 PollResult::Exhausted => Poll::Pending,
54 }
55 }
56}