4
0

macros.rs 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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. ///
  10. /// This macro requires a `critical-section` implementation to be set. For most single-hart systems,
  11. /// you can enable the `critical-section-single-hart` feature for this crate. For other systems, you
  12. /// have to provide one from elsewhere, typically your chip's HAL crate.
  13. ///
  14. /// # Example
  15. ///
  16. /// ``` no_run
  17. /// use riscv::singleton;
  18. ///
  19. /// fn main() {
  20. /// // OK if `main` is executed only once
  21. /// let x: &'static mut bool = singleton!(: bool = false).unwrap();
  22. ///
  23. /// let y = alias();
  24. /// // BAD this second call to `alias` will definitively `panic!`
  25. /// let y_alias = alias();
  26. /// }
  27. ///
  28. /// fn alias() -> &'static mut bool {
  29. /// singleton!(: bool = false).unwrap()
  30. /// }
  31. /// ```
  32. #[macro_export]
  33. macro_rules! singleton {
  34. (: $ty:ty = $expr:expr) => {
  35. $crate::_export::critical_section::with(|_| {
  36. static mut VAR: Option<$ty> = None;
  37. #[allow(unsafe_code)]
  38. let used = unsafe { VAR.is_some() };
  39. if used {
  40. None
  41. } else {
  42. let expr = $expr;
  43. #[allow(unsafe_code)]
  44. unsafe {
  45. VAR = Some(expr)
  46. }
  47. #[allow(unsafe_code)]
  48. unsafe {
  49. VAR.as_mut()
  50. }
  51. }
  52. })
  53. };
  54. }