From b0c6c4f9a45cf2b965acd3d10499e9df54929b36 Mon Sep 17 00:00:00 2001 From: Brian Cully Date: Mon, 29 Jul 2019 10:48:05 -0400 Subject: WIP: Add `const-fn` feature to attempt support for stable toolchain. To get this to work, either `FnMut` traits need to be allowed in `const fn` in stable, or `Handler::new` needs to be non-`const`. --- Cargo.toml | 1 + README.md | 4 ++++ src/handler.rs | 49 ++++++++++++++++++++++++++++++++++++++++--------- src/lib.rs | 2 +- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1079e1d..6d6f192 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ cortex-m = "~0.6" [features] default = ["isr-32"] +const-fn = [] # Number of ISR closures to hold in a HandlerTable. This is pretty # clumsy, but doesn't require const generics. diff --git a/README.md b/README.md index c3c6de5..daf4e03 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ configure the number of available slots, specify one of the following cargo features: `isr-8`, `isr-16`, `isr-32`, `isr-64`, `isr-128`, or `isr-256`. By default, 32 slots are available. +If you're using a nightly toolchain, you can enable an optimization +when calling handlers by turning on the `const-fn` feature. This will +save one conditional branch on every call. + # Example Code See the `examples` directory for some simple examples. diff --git a/src/handler.rs b/src/handler.rs index ec1f22e..545e622 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -80,20 +80,35 @@ //! unsafe { SYSTICK_HANDLER.call() }; //! } //! ``` +#[cfg(not(feature = "const-fn"))] +use core::ptr::NonNull; +#[cfg(feature = "const-fn")] pub struct Handler<'a> { // Handler that will be executed on `call`. h: *const dyn FnMut(), lifetime: core::marker::PhantomData<&'a dyn FnMut()>, } +#[cfg(not(feature = "const-fn"))] +pub struct Handler<'a> { + // Handler that will be executed on `call`. + h: Option>, +} impl<'a> Handler<'a> { /// Returns a new Handler that initially does nothing when /// called. Override its behavior by using `replace`. pub const fn new() -> Self { - Self { - h: &Self::default_handler, - lifetime: core::marker::PhantomData, + #[cfg(feature = "const-fn")] + { + Self { + h: &Self::default_handler, + lifetime: core::marker::PhantomData, + } + } + #[cfg(not(feature = "const-fn"))] + { + Self { h: None } } } @@ -105,7 +120,16 @@ impl<'a> Handler<'a> { /// while it is being executed. It is your responsibility to make /// sure that it's not being executed when you call `replace`. pub unsafe fn replace(&mut self, f: &(dyn FnMut() + Send + 'a)) { - self.h = core::mem::transmute::<_, &'a _>(f); + #[cfg(feature = "const-fn")] + { + self.h = core::mem::transmute::<_, &'a _>(f); + } + #[cfg(not(feature = "const-fn"))] + { + // let ptr: *mut dyn FnMut() = core::mem::transmute::<_, &'a _>(f); + // self.h = Some(NonNull::new(ptr)); + self.h = Some(NonNull::new_unchecked(f)); + } } /// Execute this handler. @@ -116,8 +140,15 @@ impl<'a> Handler<'a> { /// closure is being looked up. You need to ensure that `replace` /// and `call` can not occur at the same time. pub unsafe fn call(&self) { - let f: &mut dyn FnMut() = &mut *(self.h as *mut dyn FnMut()); - f(); + #[cfg(feature = "const-fn")] + { + let f: &mut dyn FnMut() = &mut *(self.h as *mut dyn FnMut()); + f(); + } + #[cfg(not(feature = "const-fn"))] + { + self.h.map(|mut f| (f.as_mut())()); + } } /// Do nothing handler. Needed by `call` until `replace` is used @@ -152,7 +183,7 @@ mod test { let mut handler = Handler::new(); unsafe { - handler.replace(&|| X += 1); + handler.replace(&mut || X += 1); assert_eq!(X, 0); handler.call(); handler.call(); @@ -166,7 +197,7 @@ mod test { static mut X: usize = 0; unsafe { - HANDLER.replace(&|| X += 1); + HANDLER.replace(&mut || X += 1); assert_eq!(X, 0); HANDLER.call(); HANDLER.call(); @@ -178,7 +209,7 @@ mod test { fn replace_with_default() { let mut handler = Handler::new(); unsafe { - handler.replace(&Handler::default_handler); + handler.replace(&mut Handler::default_handler); handler.call() } } diff --git a/src/lib.rs b/src/lib.rs index 8e16b26..d0ddad5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ //! Critical section support is supplied by the [`cs` module](cs). #![no_std] -#![feature(const_fn)] +#![cfg_attr(feature = "const-fn", feature(const_fn))] pub mod array; pub mod cs; -- cgit v1.2.3