#![no_std]
pub mod impls;
mod util;
use core::sync::atomic::{AtomicBool, Ordering};
use core::{
future::Future,
pin::Pin,
sync::atomic,
task::{Context, Poll, Waker},
};
use bare_metal::CriticalSection;
use crate::util::mutmutex::MutMutex;
use crate::util::priorityqueue::{Index, PriorityQueue};
pub const CAPACITY: usize = 32;
#[derive(Debug)]
pub struct CapacityError;
struct Handle<TIME: Ord> {
deadline: TIME,
awoken: AtomicBool,
waker: Option<Waker>,
}
impl<TIME: Ord> Handle<TIME> {
fn awaken(&self) -> bool {
let result = self.awoken.compare_and_swap(false, true, Ordering::SeqCst);
if let Some(waker) = &self.waker {
waker.wake_by_ref();
}
result
}
}
impl<TIME: Ord> PartialEq for Handle<TIME> {
fn eq(&self, other: &Self) -> bool {
self.deadline.eq(&other.deadline)
}
}
impl<TIME: Ord> PartialOrd for Handle<TIME> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.deadline.partial_cmp(&other.deadline)
}
}
pub trait Timer {
type Duration: Clone;
type Instant: Clone + Ord + core::ops::AddAssign<Self::Duration>;
const DELTA: Self::Duration;
fn reset(&mut self);
fn interrupt_free<F: FnOnce(&CriticalSection) -> R, R>(f: F) -> R;
fn now(&self) -> Self::Instant;
fn disarm(&mut self);
fn arm(&mut self, deadline: &Self::Instant);
}
#[inline(always)]
fn future<D, I: Clone + core::ops::AddAssign<D>>(mut i: I, d: D) -> I {
i += d;
i
}
pub struct Delay<'a, T: Timer> {
index: Index,
timer: &'a AsyncTimer<T>,
}
impl<'a, T: Timer> Future for Delay<'a, T> {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
T::interrupt_free(|cs| {
let inner = unsafe { self.timer.0.borrow_mut(cs) };
let handle = inner.handles.get_mut(self.index).unwrap(); let waker = &mut handle.waker;
if handle.awoken.load(Ordering::SeqCst) {
if waker.is_none() {
drop(waker.take());
}
Poll::Ready(())
} else {
waker.replace(cx.waker().clone());
drop(inner);
atomic::compiler_fence(Ordering::Release);
self.timer.wake_and_arm(cs);
Poll::Pending
}
})
}
}
impl<'a, T: Timer> Drop for Delay<'a, T> {
fn drop(&mut self) {
T::interrupt_free(|cs| {
let inner = unsafe { self.timer.0.borrow_mut(cs) };
inner.handles.remove(self.index).unwrap(); });
}
}
struct AsyncTimerInner<T: Timer> {
handles: PriorityQueue<Handle<T::Instant>>,
timer: T,
}
pub struct AsyncTimer<T: Timer>(MutMutex<AsyncTimerInner<T>>);
impl<T: Timer> AsyncTimer<T> {
pub fn new(timer: T) -> Self {
Self(MutMutex::new(AsyncTimerInner {
handles: PriorityQueue::new(),
timer,
}))
}
pub fn reset(&self) {
T::interrupt_free(|cs| {
let inner = unsafe { self.0.borrow_mut(cs) };
inner.timer.reset()
})
}
pub fn now(&self) -> T::Instant {
T::interrupt_free(|cs| {
let inner = unsafe { self.0.borrow_mut(cs) };
inner.timer.now()
})
}
pub unsafe fn get_inner<U>(&self, f: impl FnOnce(&mut T) -> U) -> U {
T::interrupt_free(|cs| f(&mut self.0.borrow_mut(cs).timer))
}
fn wake_and_arm(&self, cs: &CriticalSection) {
let inner = unsafe { self.0.borrow_mut(cs) };
let time = inner.timer.now();
let earliest = inner.handles.iter().try_fold((), |_, (_index, handle)| {
if handle.deadline <= time {
handle.awaken();
Ok(())
} else {
Err(&handle.deadline)
}
});
match earliest {
Ok(()) => {
inner.timer.disarm(); }
Err(earliest) => {
let min_next = future(inner.timer.now(), T::DELTA);
if min_next < *earliest {
inner.timer.arm(earliest);
} else {
inner.timer.arm(&min_next);
}
}
}
}
#[inline(always)]
pub fn awaken(&self) {
T::interrupt_free(|cs| {
self.wake_and_arm(cs);
});
}
#[inline(always)]
pub fn wait<'a>(&'a self, dur: T::Duration) -> Result<Delay<'a, T>, CapacityError> {
self.wait_until_always(future(self.now(), dur))
}
#[inline(always)]
pub async fn wait_until<'a>(&'a self, deadline: T::Instant) -> Result<(), CapacityError> {
if deadline <= self.now() {
return Ok(());
}
Ok(self.wait_until_always(deadline)?.await)
}
#[inline(always)]
pub fn wait_until_always<'a>(
&'a self,
deadline: T::Instant,
) -> Result<Delay<'a, T>, CapacityError> {
let handle = Handle {
deadline,
awoken: AtomicBool::new(false),
waker: None,
};
let index = T::interrupt_free(|cs| {
let inner = unsafe { self.0.borrow_mut(cs) };
inner.handles.insert(handle)
})?;
Ok(Delay { index, timer: self })
}
}
pub struct Interval<CLOCK: Timer> {
last: CLOCK::Instant,
duration: CLOCK::Duration,
}
impl<CLOCK: Timer> Interval<CLOCK> {
pub fn new(duration: CLOCK::Duration, timer: &AsyncTimer<CLOCK>) -> Self {
Self {
last: timer.now(),
duration,
}
}
pub fn wait<'a>(&mut self, timer: &'a AsyncTimer<CLOCK>) -> impl Future + 'a {
self.last += self.duration.clone();
timer.wait_until(self.last.clone())
}
}