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
95
/* 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)]
#[inline(always)]
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()
}
})
}
};
}