diff options
author | 2017-12-23 11:24:18 +0100 | |
---|---|---|
committer | 2017-12-23 11:24:18 +0100 | |
commit | 74045f24f8bd2dcee6c1dcde0f9db63de192d7e5 (patch) | |
tree | e24eb9d65e3ff6a39ce41002a0c63f7d5895cf2f /src | |
parent | 9a80bae79d1eb9111e50406cb7cc088246deb04d (diff) | |
download | cortex-m-74045f24f8bd2dcee6c1dcde0f9db63de192d7e5.tar.gz cortex-m-74045f24f8bd2dcee6c1dcde0f9db63de192d7e5.tar.zst cortex-m-74045f24f8bd2dcee6c1dcde0f9db63de192d7e5.zip |
safe `&'static mut` references through a runtime checked macro
Diffstat (limited to 'src')
-rw-r--r-- | src/macros.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/macros.rs b/src/macros.rs index 465d759..bd43b4f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,3 +22,44 @@ macro_rules! iprintln { iprint!($channel, concat!($fmt, "\n"), $($arg)*); }; } + +/// Macro to create an statically allocated value +/// +/// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned +/// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a +/// `None` variant the caller must ensure that the macro is called from a function that's executed +/// at most once in the whole lifetime of the program. +/// +/// # Example +/// +/// ``` ignore +/// fn main() { +/// // OK if `main` is executed only once +/// let x: &'static mut bool = static_!(: bool = false).unwrap(); +/// +/// let y = alias(); +/// // BAD this second call to `alias` will definitively `panic!` +/// let y_alias = alias(); +/// } +/// +/// fn alias() -> &'static mut bool { +/// static_!(: bool = false).unwrap() +/// } +/// ``` +#[macro_export] +macro_rules! static_ { + (: $ty:ty = $expr:expr) => { + $crate::interrupt::free(|_| unsafe { + static mut USED: bool = false; + static mut VAR: $ty = $expr; + + if USED { + None + } else { + USED = true; + let var: &'static mut _ = &mut VAR; + Some(var) + } + }) + } +} |