1pub mod future;
2mod join;
3pub mod machine;
4mod pending;
5mod pollfn;
6pub mod race;
7mod ready;
8mod task;
9
10use core::{pin, task::Poll};
11use o3::{
12 base::cell::region,
13 mem::{self, slot},
14};
15
16pub use join::Join;
17pub use pending::Pending;
18pub use pollfn::{PollFn, poll_fn};
19pub use ready::Ready;
20pub use task::Task;
21
22use crate::context;
23
24#[derive(Clone, Copy, Debug)]
25enum Side {
26 Left,
27 Right,
28}
29
30impl Side {
31 const fn other(self) -> Self {
32 match self {
33 Self::Left => Self::Right,
34 Self::Right => Self::Left,
35 }
36 }
37}
38
39#[must_use = "a fiber does nothing unless it is driven"]
40pub trait Fiber<'d>: Sized {
44 type Output;
45
46 fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> Poll<Self::Output>;
47}
48
49#[must_use = "a stream does nothing unless it is driven"]
53pub trait Stream<'d>: Sized {
54 type Item;
55
56 fn poll_next(call: context::PollCall<'_, '_, 'd, Self>) -> Poll<Option<Self::Item>>;
57}
58
59pub trait Resume<'d>: Sized + Unpin {
61 type Output;
62 type Ready;
63
64 fn poll<'slot, 'id>(
65 live: &mut Live<'slot, 'id, Self>,
66 admit: &mut context::Admission<'_, '_, 'd>,
67 ) -> Poll<Self::Ready>;
68
69 fn finish<'slot, 'id>(
70 live: Live<'slot, 'id, Self>,
71 ready: Self::Ready,
72 admit: context::Admission<'_, '_, 'd>,
73 ) -> Transition<'id, Self::Output>;
74}
75
76#[repr(transparent)]
78#[must_use = "a task does nothing unless it is driven"]
79pub struct Owned<F> {
80 state: slot::Storage<F>,
81}
82
83impl<F> Owned<F> {
84 pub const fn new(value: F) -> Self {
85 Self {
86 state: slot::Storage::filled(value, ()),
87 }
88 }
89}
90
91pub struct Live<'slot, 'id, F> {
93 slot: mem::raw::Occupied<'slot, F>,
94 proof: region::Proof<region::Identity<'id>>,
95}
96
97impl<'slot, 'id, F> Live<'slot, 'id, F> {
98 pub fn get_mut(&mut self) -> &mut F {
99 self.slot.get_mut()
100 }
101
102 pub fn pending<O>(self) -> Transition<'id, O> {
103 Transition {
104 poll: Poll::Pending,
105 _proof: self.proof,
106 }
107 }
108
109 pub fn take(self) -> (Vacant<'slot, 'id, F>, F) {
110 let (value, slot) = self.slot.take();
111 (
112 Vacant {
113 slot,
114 proof: self.proof,
115 },
116 value,
117 )
118 }
119}
120
121pub struct Vacant<'slot, 'id, F> {
123 slot: mem::raw::Vacant<'slot, F>,
124 proof: region::Proof<region::Identity<'id>>,
125}
126
127impl<'slot, 'id, F> Vacant<'slot, 'id, F> {
128 pub fn insert(self, value: F) -> Live<'slot, 'id, F> {
129 Live {
130 slot: self.slot.insert(value),
131 proof: self.proof,
132 }
133 }
134
135 pub fn complete<O>(self, output: O) -> Transition<'id, O> {
136 Transition {
137 poll: Poll::Ready(output),
138 _proof: self.proof,
139 }
140 }
141}
142
143pub struct Transition<'id, O> {
145 poll: Poll<O>,
146 _proof: region::Proof<region::Identity<'id>>,
147}
148
149impl<'d, F: Resume<'d>> Fiber<'d> for Owned<F> {
150 type Output = F::Output;
151
152 fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> Poll<Self::Output> {
153 let (this, mut admit) = call.into_admit();
154 let Some(slot) = this.get_mut().state.occupied() else {
155 return Poll::Pending;
156 };
157 region::Token::scope(|token| {
158 let mut live = Live {
159 slot,
160 proof: token.proof(),
161 };
162 match F::poll(&mut live, &mut admit) {
163 Poll::Pending => live.pending(),
164 Poll::Ready(ready) => F::finish(live, ready, admit),
165 }
166 .poll
167 })
168 }
169}
170
171impl<'d, F: Fiber<'d>> Fiber<'d> for pin::Pin<&mut Task<F>> {
172 type Output = F::Output;
173
174 fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> Poll<Self::Output> {
175 Task::<F>::poll(call.map(|fiber| fiber.get_mut().as_mut()))
176 }
177}