File tree Expand file tree Collapse file tree 2 files changed +57
-0
lines changed Expand file tree Collapse file tree 2 files changed +57
-0
lines changed Original file line number Diff line number Diff line change @@ -22,3 +22,6 @@ extern crate bit_field;
2222pub mod asm;
2323pub mod interrupt;
2424pub mod register;
25+
26+ #[ macro_use]
27+ mod macros;
Original file line number Diff line number Diff line change 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+ /// # Note
9+ /// this macro is unsound on multi-core systems
10+ ///
11+ /// # Example
12+ ///
13+ /// ``` no_run
14+ /// use riscv::singleton;
15+ ///
16+ /// fn main() {
17+ /// // OK if `main` is executed only once
18+ /// let x: &'static mut bool = singleton!(: bool = false).unwrap();
19+ ///
20+ /// let y = alias();
21+ /// // BAD this second call to `alias` will definitively `panic!`
22+ /// let y_alias = alias();
23+ /// }
24+ ///
25+ /// fn alias() -> &'static mut bool {
26+ /// singleton!(: bool = false).unwrap()
27+ /// }
28+ /// ```
29+ #[ macro_export]
30+ macro_rules! singleton {
31+ ( : $ty: ty = $expr: expr) => {
32+ $crate:: interrupt:: free( |_| {
33+ static mut VAR : Option <$ty> = None ;
34+
35+ #[ allow( unsafe_code) ]
36+ let used = unsafe { VAR . is_some( ) } ;
37+ if used {
38+ None
39+ } else {
40+ let expr = $expr;
41+
42+ #[ allow( unsafe_code) ]
43+ unsafe {
44+ VAR = Some ( expr)
45+ }
46+
47+ #[ allow( unsafe_code) ]
48+ unsafe {
49+ VAR . as_mut( )
50+ }
51+ }
52+ } )
53+ } ;
54+ }
You can’t perform that action at this time.
0 commit comments