1#![no_std]
2#![feature(waker_getters)]
3
4pub mod impls;
5
6struct BoundedEventSourceId(usize);
9
10use core::{
11 cell::RefCell, future::Future, hint::unreachable_unchecked, pin::Pin, sync::atomic::AtomicPtr,
12 usize,
13};
14
15use futures::future::FusedFuture;
16use impls::no_heap::SingleThreadMarshall;
17
18pub const fn raw_waker_v_table<Marshall: ExecutorMarshall>() -> core::task::RawWakerVTable {
19 unsafe fn clone<Marshall: ExecutorMarshall>(marshall: *const ()) -> core::task::RawWaker {
20 let waker = Marshall::waker(&*(marshall as *const Marshall));
21 let raw = waker.as_raw();
22 let raw = core::task::RawWaker::new(raw.data(), raw.vtable());
23 core::mem::forget(waker);
24 raw
25 }
26 unsafe fn wake<Marshall: ExecutorMarshall>(marshall: *const ()) {
27 wake_by_ref::<Marshall>(marshall)
29 }
30 unsafe fn wake_by_ref<Marshall: ExecutorMarshall>(marshall: *const ()) {
31 let marshall = &*(marshall as *const Marshall);
32 marshall.wake();
33 }
34 unsafe fn drop<Marshall: ExecutorMarshall>(_marshall: *const ()) {
35 }
37 core::task::RawWakerVTable::new(
38 clone::<Marshall>,
39 wake::<Marshall>,
40 wake_by_ref::<Marshall>,
41 drop::<Marshall>,
42 )
43}
44
45pub trait ExecutorMarshall: Sync + 'static {
53 fn wake(&'static self);
54 fn waker(&'static self) -> core::task::Waker;
55}
56
57pub struct Executor<'a, Tasks: TaskManager, Pool: EventSourcePool> {
58 tasks: &'a mut Tasks,
59 pool: &'a mut Pool,
60}
61
62pub enum WakeStatus {
63 Woken,
64 Asleep,
65}
66
67pub trait TaskManager {
68 type Marshall: ExecutorMarshall;
69 type TaskIterator<'a>: Iterator<
70 Item = (
71 Pin<&'a mut dyn FusedFutureWithWakeStatus<Output = ()>>,
72 &'static Self::Marshall,
73 ),
74 >
75 where
76 Self: 'a;
77 fn get_task(
78 &mut self,
79 i: usize,
80 ) -> Option<(
81 Pin<&mut dyn FusedFutureWithWakeStatus<Output = ()>>,
82 &'static Self::Marshall,
83 )>;
84 fn sleep_task(&mut self, i: usize);
85 fn sleep_all(&mut self);
86 fn tasks<'a>(&'a mut self) -> Self::TaskIterator<'a>;
87}
88
89pub trait EventSourcePool: Context {
90 type SourceIterator<'a>: Iterator<Item = &'a mut Source>
91 where
92 Self: 'a;
93
94 fn sources<'a>(&'a mut self) -> Self::SourceIterator<'a>;
95}
96
97pub trait Context {
98 type Id;
99 unsafe fn register_source(&self, source: *mut dyn EventSource) -> Option<Self::Id>;
100 fn unregister_source(&self, id: Self::Id);
101}
102
103struct BoundedEventSourcePool<const N: usize> {
104 slots: RefCell<[Option<*mut dyn EventSource>; N]>,
105}
106
107impl<const N: usize> Context for BoundedEventSourcePool<N> {
108 type Id = BoundedEventSourceId;
109
110 unsafe fn register_source(&self, source: *mut dyn EventSource) -> Option<Self::Id> {
111 let mut slots = self.slots.borrow_mut();
112 if let Some((i, empty_slot)) = slots
113 .iter_mut()
114 .enumerate()
115 .find(|(_, slot)| slot.is_none())
116 {
117 *empty_slot = Some(source);
118 Some(BoundedEventSourceId(i))
119 } else {
120 None
121 }
122 }
123
124 fn unregister_source(&self, id: Self::Id) {
125 self.slots.borrow_mut()[id.0] = None;
126 }
127}
128
129pub trait EventSource {
130 fn setup(&mut self);
131
132 fn check(&mut self);
133
134 fn cleanup(self);
135}
136
137pub trait FusedFutureWithWakeStatus: FusedFuture {
138 fn status(&self) -> WakeStatus;
139 fn set_status(self: Pin<&mut Self>, status: WakeStatus);
140}
141
142pub trait FusedFutureExt {
143 fn with_wake_status_st(self) -> SingleThreadWithWakeStatus<Self>
144 where
145 Self: Sized;
146}
147
148#[pin_project::pin_project]
149pub struct SingleThreadWithWakeStatus<F> {
150 #[pin]
151 f: F,
152 status: core::cell::Cell<bool>,
153}
154
155impl<F> SingleThreadWithWakeStatus<F> {
156 pub unsafe fn register(self: Pin<&mut Self>, marshall: &'static SingleThreadMarshall) {
157 let projection = self.project();
158 marshall.register(&projection.status);
159 }
160}
161
162impl<F: Future> Future for SingleThreadWithWakeStatus<F> {
163 type Output = F::Output;
164
165 fn poll(
166 self: Pin<&mut Self>,
167 cx: &mut core::task::Context<'_>,
168 ) -> core::task::Poll<Self::Output> {
169 let projection = self.project();
170 projection.f.poll(cx)
171 }
172}
173
174impl<F: FusedFuture> FusedFuture for SingleThreadWithWakeStatus<F> {
175 fn is_terminated(&self) -> bool {
176 self.f.is_terminated()
177 }
178}
179
180impl<F: FusedFuture> FusedFutureWithWakeStatus for SingleThreadWithWakeStatus<F> {
181 fn status(&self) -> WakeStatus {
182 if self.status.get() {
183 WakeStatus::Woken
184 } else {
185 WakeStatus::Asleep
186 }
187 }
188
189 fn set_status(self: Pin<&mut Self>, status: WakeStatus) {
190 match status {
191 WakeStatus::Woken => self.status.set(true),
192 WakeStatus::Asleep => self.status.set(false),
193 }
194 }
195}
196
197impl<F: futures::future::FusedFuture> FusedFutureExt for F {
198 fn with_wake_status_st(self) -> SingleThreadWithWakeStatus<Self> {
199 SingleThreadWithWakeStatus {
200 f: self,
201 status: core::cell::Cell::new(true),
202 }
203 }
204}
205
206pub enum Source {
207 Poll {},
208}
209
210impl<'a, Tasks: TaskManager, Pool: EventSourcePool> Executor<'a, Tasks, Pool> {
211 pub fn new(tasks: &'a mut Tasks, pool: &'a mut Pool) -> Self {
212 Executor { tasks, pool }
213 }
214
215 pub fn run_to_completion(self) {
216 while self.tasks.tasks().any(|(task, _)| !task.is_terminated()) {
217 for (i, (mut task, marshall)) in
218 self.tasks.tasks().enumerate().filter(|(_, (task, _))| {
219 !task.is_terminated() && matches!(task.status(), WakeStatus::Woken)
220 })
221 {
222 let waker = marshall.waker();
223 let mut context: core::task::Context<'_> = core::task::Context::from_waker(&waker);
224 task.as_mut().set_status(WakeStatus::Asleep);
225 let _ = task.poll(&mut context);
226 }
227 }
229 }
230}