1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
/* mutstatic.rs
*
* Developed by Tim Walls <tim.walls@snowgoons.com>
* Copyright (c) All Rights Reserved, Tim Walls
*/
//! Mutable static singleton helper
#[doc(hidden)]
#[macro_export]
macro_rules! mut_singleton {
($type:ty, $name:ident, $accessor:ident, $accessor_isolated:ident, $constructor:expr) => {
static mut $name : Option<$type> = None;
/**
* Return a reference to the global singleton instance of $type. The
* caller should pass an isolation token obtained by
* [`avr_oxide::concurrency::interrupt::isolated()`]
*/
#[allow(dead_code)]
#[inline(never)]
pub fn $accessor_isolated(_isotoken: avr_oxide::concurrency::Isolated) -> &'static mut $type {
unsafe {
if $name.is_none() {
core::ptr::replace(&mut $name, Some($constructor));
}
match &mut $name {
None => avr_oxide::oserror::halt(avr_oxide::oserror::OsError::InternalError),
Some(instance) => instance
}
}
}
/**
* Return a reference to a global singleton instance of $type.
* Interrupts will be locked for the duration of the call to ensure
* consistency; if calling from a context wherein interrupts are
* already disabled, calling $accessor_isolated() will be more
* efficient.
*/
#[allow(dead_code)]
pub fn $accessor() -> &'static mut $type {
avr_oxide::concurrency::interrupt::isolated(|isotoken|{
$accessor_isolated(isotoken)
})
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! mut_singleton_explicit_init {
($type:ty, $name:ident, $initialiser:ident, $accessor:ident, $accessor_isolated:ident, $constructor:expr) => {
static mut $name : core::mem::MaybeUninit<$type> = core::mem::MaybeUninit::uninit();
/**
* Inititalise the global singleton of $type.
*/
pub unsafe fn $initialiser() {
core::ptr::write(
$name.as_mut_ptr(),
$constructor
);
}
/**
* Return a reference to the global singleton instance of $type. The
* caller should pass an isolation token obtained by
* [`avr_oxide::concurrency::interrupt::isolated()`]
*/
#[allow(dead_code)]
pub fn $accessor_isolated(_isotoken: avr_oxide::concurrency::Isolated) -> &'static mut $type {
unsafe {
$name.assume_init_mut()
}
}
/**
* Return a reference to a global singleton instance of $type.
* Interrupts will be locked for the duration of the call to ensure
* consistency; if calling from a context wherein interrupts are
* already disabled, calling $accessor_isolated() will be more
* efficient.
*/
#[allow(dead_code)]
pub fn $accessor() -> &'static mut $type {
avr_oxide::concurrency::interrupt::isolated(|isotoken|{
unsafe {
$name.assume_init_mut()
}
})
}
};
}