File tree 2 files changed +57
-0
lines changed
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;
22
22
pub mod asm;
23
23
pub mod interrupt;
24
24
pub 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