Added interface for cancel/reschedule

Use wrapping add for marker

No need to store handle to queue

Remove unnecessary `SpawnHandle::new`

Fix test

Updated interface to follow proposal
This commit is contained in:
Emil Fresk 2021-03-11 19:12:02 +01:00
parent 4bdc187912
commit 1087f2ee64
6 changed files with 108 additions and 249 deletions

View file

@ -264,15 +264,64 @@ pub fn codegen(
};
let user_imports = &app.user_imports;
let tq_marker = util::mark_internal_ident(&util::timer_queue_marker_ident());
items.push(quote!(
/// Holds methods related to this monotonic
pub mod #m {
#[allow(unused_imports)]
use #app_path::#tq_marker;
#[allow(unused_imports)]
use #app_path::#t;
#(
#[allow(unused_imports)]
#user_imports
)*
pub struct SpawnHandle {
#[doc(hidden)]
marker: u32,
}
// TODO: remove
impl core::fmt::Debug for SpawnHandle
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let handle = unsafe { &#app_path::#tq as *const _ as u32 };
f.debug_struct("SpawnHandle")
.field("marker", &self.marker)
.field("handle", &handle)
.finish()
}
}
impl SpawnHandle {
pub fn cancel(self) -> Result<#ty, ()> {
// TODO: Actually cancel...
// &mut #app_path::#tq;
Err(())
}
#[inline]
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()>
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>,
{
self.reschedule_at(#app_path::#m::now() + duration)
}
pub fn reschedule_at(self, instant: rtic::time::Instant<#app_path::#mono_type>) -> Result<Self, ()>
{
let _ = instant;
// TODO: Actually reschedule...
// &mut #app_path::#tq;
Err(())
}
}
#(#cfgs)*
/// Spawns the task after a set duration relative to the current time
///
@ -281,7 +330,7 @@ pub fn codegen(
pub fn spawn_after<D>(
duration: D
#(,#args)*
) -> Result<(), #ty>
) -> Result<SpawnHandle, #ty>
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>,
{
@ -300,7 +349,7 @@ pub fn codegen(
pub fn spawn_at(
instant: rtic::time::Instant<#app_path::#mono_type>
#(,#args)*
) -> Result<(), #ty> {
) -> Result<SpawnHandle, #ty> {
unsafe {
let input = #tupled;
if let Some(index) = rtic::export::interrupt::free(|_| #app_path::#fq.dequeue()) {
@ -314,13 +363,17 @@ pub fn codegen(
.as_mut_ptr()
.write(instant);
let nr = rtic::export::NotReady {
instant,
index,
task: #app_path::#t::#name,
};
rtic::export::interrupt::free(|_| {
let marker = #tq_marker;
let nr = rtic::export::NotReady {
instant,
index,
task: #app_path::#t::#name,
marker,
};
#tq_marker = #tq_marker.wrapping_add(1);
rtic::export::interrupt::free(|_|
if let Some(mono) = #app_path::#m_ident.as_mut() {
#app_path::#tq.enqueue_unchecked(
nr,
@ -331,9 +384,10 @@ pub fn codegen(
// We can only use the timer queue if `init` has returned, and it
// writes the `Some(monotonic)` we are accessing here.
core::hint::unreachable_unchecked()
});
}
Ok(())
Ok(SpawnHandle { marker })
})
} else {
Err(input)
}

View file

@ -9,6 +9,15 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
let mut items = vec![];
if !app.monotonics.is_empty() {
// Generate the marker counter used to track for `cancel` and `reschedule`
let tq_marker = util::mark_internal_ident(&util::timer_queue_marker_ident());
items.push(quote!(
// #[doc = #doc]
#[doc(hidden)]
#[allow(non_camel_case_types)]
static mut #tq_marker: u32 = 0;
));
let t = util::schedule_t_ident();
// Enumeration of `schedule`-able tasks
@ -32,7 +41,7 @@ pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStrea
#[doc(hidden)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
enum #t {
pub enum #t {
#(#variants,)*
}
));

View file

@ -89,6 +89,11 @@ pub fn interrupt_ident() -> Ident {
Ident::new("interrupt", span)
}
pub fn timer_queue_marker_ident() -> Ident {
let span = Span::call_site();
Ident::new("TIMER_QUEUE_MARKER", span)
}
/// Whether `name` is an exception with configurable priority
pub fn is_exception(name: &Ident) -> bool {
let s = name.to_string();