lock_free_static/
static_.rs1use crate::{OnceCell, OnceMut};
2use core::ops::Deref;
3
4pub struct LockFreeStatic<T, D, F: Fn() -> T = fn() -> T> {
9 base: D,
10 ctor: F,
11}
12
13impl<T, D, F: Fn() -> T> Deref for LockFreeStatic<T, D, F> {
14 type Target = D;
15 fn deref(&self) -> &Self::Target {
16 &self.base
17 }
18}
19
20impl<T, D, F: Fn() -> T> LockFreeStatic<T, D, F> {
21 pub const fn new(base: D, ctor: F) -> Self {
23 Self { base, ctor }
24 }
25}
26
27impl<T, F: Fn() -> T> LockFreeStatic<T, OnceCell<T>, F> {
28 #[must_use]
32 pub fn init(&self) -> bool {
33 self.base.set((self.ctor)()).is_ok()
34 }
35}
36
37impl<T, F: Fn() -> T> LockFreeStatic<T, OnceMut<T>, F> {
38 #[must_use]
42 pub fn init(&self) -> bool {
43 self.base.set((self.ctor)()).is_ok()
44 }
45}
46
47#[macro_export]
49macro_rules! lock_free_static {
50 ($(#[$attr:meta])* $vis:vis static $ident:ident: $ty:ty = $expr:expr; $($next:tt)*) => {
51 $(#[$attr])*
52 $vis static $ident: $crate::LockFreeStatic<$ty, $crate::OnceCell<$ty>>
53 = $crate::LockFreeStatic::new($crate::OnceCell::new(), || $expr);
54 $crate::lock_free_static!($($next)*);
55 };
56 ($(#[$attr:meta])* $vis:vis static mut $ident:ident: $ty:ty = $expr:expr; $($next:tt)*) => {
57 $(#[$attr])*
58 $vis static $ident: $crate::LockFreeStatic<$ty, $crate::OnceMut<$ty>>
59 = $crate::LockFreeStatic::new($crate::OnceMut::new(), || $expr);
60 $crate::lock_free_static!($($next)*);
61 };
62 () => {};
63}
64
65#[cfg(test)]
66mod tests {
67 lock_free_static! {
68 static CONST: i32 = 123;
69 }
70
71 #[test]
72 fn const_() {
73 assert!(CONST.get().is_none());
74 assert!(CONST.init());
75
76 let value = CONST.get().unwrap();
77 assert_eq!(*value, 123);
78 assert_eq!(*CONST.get().unwrap(), 123);
79 }
80
81 lock_free_static! {
82 static mut MUT: i32 = 123;
83 }
84
85 #[test]
86 fn mut_() {
87 assert!(MUT.lock().is_none());
88 assert!(MUT.init());
89
90 let mut guard = MUT.lock().unwrap();
91 assert_eq!(*guard, 123);
92 assert!(MUT.lock().is_none());
93 *guard = 321;
94 drop(guard);
95
96 assert_eq!(*MUT.lock().unwrap(), 321);
97 }
98
99 lock_free_static! {
100 static ONE: i32 = 1;
101 static mut TWO: i32 = 2;
102 }
103
104 #[test]
105 fn multiple() {
106 assert!(ONE.init());
107 assert!(TWO.init());
108 assert_eq!(*ONE.get().unwrap(), 1);
109 assert_eq!(*ONE.get().unwrap(), 1);
110 assert_eq!(*TWO.get_mut().unwrap(), 2);
111 assert!(TWO.get_mut().is_none());
112 }
113
114 mod outer {
115 lock_free_static! {
116 pub static ONE: i32 = 1;
117 pub static mut TWO: i32 = 2;
118 }
119 }
120
121 #[test]
122 fn visibility() {
123 assert!(outer::ONE.init());
124 assert!(outer::TWO.init());
125 assert_eq!(*outer::ONE.get().unwrap(), 1);
126 assert_eq!(*outer::TWO.get_mut().unwrap(), 2);
127 }
128}