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 use crate::lock_free_static;
68
69 lock_free_static! {
70 static CONST: i32 = 123;
71 }
72
73 #[test]
74 fn const_() {
75 assert!(CONST.get().is_none());
76 assert!(CONST.init());
77
78 let value = CONST.get().unwrap();
79 assert_eq!(*value, 123);
80 assert_eq!(*CONST.get().unwrap(), 123);
81 }
82
83 lock_free_static! {
84 static mut MUT: i32 = 123;
85 }
86
87 #[test]
88 fn mut_() {
89 assert!(MUT.lock().is_none());
90 assert!(MUT.init());
91
92 let mut guard = MUT.lock().unwrap();
93 assert_eq!(*guard, 123);
94 assert!(MUT.lock().is_none());
95 *guard = 321;
96 drop(guard);
97
98 assert_eq!(*MUT.lock().unwrap(), 321);
99 }
100
101 lock_free_static! {
102 static ONE: i32 = 1;
103 static mut TWO: i32 = 2;
104 }
105
106 #[test]
107 fn multiple() {
108 assert!(ONE.init());
109 assert!(TWO.init());
110 assert_eq!(*ONE.get().unwrap(), 1);
111 assert_eq!(*ONE.get().unwrap(), 1);
112 assert_eq!(*TWO.get_mut().unwrap(), 2);
113 assert!(TWO.get_mut().is_none());
114 }
115
116 mod outer {
117 use crate::lock_free_static;
118
119 lock_free_static! {
120 pub static ONE: i32 = 1;
121 pub static mut TWO: i32 = 2;
122 }
123 }
124
125 #[test]
126 fn visibility() {
127 assert!(outer::ONE.init());
128 assert!(outer::TWO.init());
129 assert_eq!(*outer::ONE.get().unwrap(), 1);
130 assert_eq!(*outer::TWO.get_mut().unwrap(), 2);
131 }
132}