macros.rs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  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. #[allow(unsafe_code)]
  35. let used = unsafe { VAR.is_some() };
  36. if used {
  37. None
  38. } else {
  39. let expr = $expr;
  40. #[allow(unsafe_code)]
  41. unsafe {
  42. VAR = Some(expr)
  43. }
  44. #[allow(unsafe_code)]
  45. unsafe {
  46. VAR.as_mut()
  47. }
  48. }
  49. })
  50. };
  51. }