Skip to content

Commit df9dda7

Browse files
committed
add singleton macro
1 parent be2927e commit df9dda7

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@ extern crate bit_field;
2222
pub mod asm;
2323
pub mod interrupt;
2424
pub mod register;
25+
26+
#[macro_use]
27+
mod macros;

src/macros.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/// Macro to create a mutable reference to a statically allocated value
2+
///
3+
/// This macro returns a value with type `Option<&'static mut $ty>`. `Some($expr)` will be returned
4+
/// the first time the macro is executed; further calls will return `None`. To avoid `unwrap`ping a
5+
/// `None` variant the caller must ensure that the macro is called from a function that's executed
6+
/// at most once in the whole lifetime of the program.
7+
///
8+
/// # Example
9+
///
10+
/// ``` no_run
11+
/// use cortex_m::singleton;
12+
///
13+
/// fn main() {
14+
/// // OK if `main` is executed only once
15+
/// let x: &'static mut bool = singleton!(: bool = false).unwrap();
16+
///
17+
/// let y = alias();
18+
/// // BAD this second call to `alias` will definitively `panic!`
19+
/// let y_alias = alias();
20+
/// }
21+
///
22+
/// fn alias() -> &'static mut bool {
23+
/// singleton!(: bool = false).unwrap()
24+
/// }
25+
/// ```
26+
#[macro_export]
27+
macro_rules! singleton {
28+
(: $ty:ty = $expr:expr) => {
29+
$crate::interrupt::free(|_| {
30+
static mut VAR: Option<$ty> = None;
31+
32+
#[allow(unsafe_code)]
33+
let used = unsafe { VAR.is_some() };
34+
if used {
35+
None
36+
} else {
37+
let expr = $expr;
38+
39+
#[allow(unsafe_code)]
40+
unsafe {
41+
VAR = Some(expr)
42+
}
43+
44+
#[allow(unsafe_code)]
45+
unsafe {
46+
VAR.as_mut()
47+
}
48+
}
49+
})
50+
};
51+
}

0 commit comments

Comments
 (0)