1use core::{
2 cell::RefCell,
3 pin::Pin,
4 task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
5};
6use futures::Future;
7use once_cell::unsync::OnceCell;
8
9pub trait Interrupt {
10 fn pend(&self);
11}
12
13#[cfg_attr(docsrs, doc(cfg(feature = "executor")))]
25pub struct Executor<I, F> {
26 interrupt: I,
27 future: OnceCell<RefCell<F>>,
28}
29
30impl<I, F> Executor<I, F> {
31 pub const fn new(interrupt: I) -> Self {
33 Self {
34 future: OnceCell::new(),
35 interrupt,
36 }
37 }
38
39 pub fn spawn(&self, future: F) -> Result<(), F> {
42 self.future
43 .set(RefCell::new(future))
44 .map_err(|cell| cell.into_inner())
45 }
46
47 pub fn poll(&'static self) -> Poll<F::Output>
49 where
50 I: Interrupt,
51 F: Future,
52 {
53 static VTABLE: RawWakerVTable = RawWakerVTable::new(
54 |ptr| RawWaker::new(ptr, &VTABLE),
55 |ptr| {
56 let me = unsafe { *ptr.cast::<&dyn Interrupt>() };
57 me.pend();
58 },
59 |ptr| {
60 let me = unsafe { *ptr.cast::<&dyn Interrupt>() };
61 me.pend();
62 },
63 |_| {},
64 );
65 let raw_waker = RawWaker::new(self as *const dyn Interrupt as *const (), &VTABLE);
66 let waker = unsafe { Waker::from_raw(raw_waker) };
67 let mut cx = Context::from_waker(&waker);
68
69 let mut future = self.future.get().unwrap().borrow_mut();
70
71 let pinned = unsafe { Pin::new_unchecked(&mut *future) };
73 pinned.poll(&mut cx)
74 }
75}
76
77impl<I: Interrupt, F> Interrupt for Executor<I, F> {
78 fn pend(&self) {
79 self.interrupt.pend()
80 }
81}