dope_fiber/task/local/
once.rs1use 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}