Skip to main content

dope_fiber/task/local/
once.rs

1use core::{marker, task};
2
3use o3::base::cell::{local, region};
4
5use crate::{abi, context};
6
7#[must_use = "a fiber does nothing unless it is driven"]
8pub struct Once<'d, F, R> {
9    call: Option<F>,
10    brand: marker::PhantomData<fn(&'d ()) -> &'d ()>,
11    output: marker::PhantomData<fn() -> R>,
12}
13
14impl<'d, F, R> Once<'d, F, R>
15where
16    F: for<'a> FnOnce(local::Access<'a, region::Identity<'d>>) -> R,
17{
18    pub const fn new(call: F) -> Self {
19        Self {
20            call: Some(call),
21            brand: marker::PhantomData,
22            output: marker::PhantomData,
23        }
24    }
25}
26
27impl<F, R> Unpin for Once<'_, F, R> {}
28
29impl<'d, F, R> abi::Fiber<'d> for Once<'d, F, R>
30where
31    F: for<'a> FnOnce(local::Access<'a, region::Identity<'d>>) -> R,
32{
33    type Output = R;
34
35    fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> task::Poll<Self::Output> {
36        let (this, mut context) = call.into_parts();
37        let this = this.get_mut();
38        let Some(call) = this.call.take() else {
39            return task::Poll::Pending;
40        };
41        let access = local::Access::new(context.as_mut().region_token());
42        task::Poll::Ready(call(access))
43    }
44}