fast_able/
static_type_std.rs1use std::{
2 cell::UnsafeCell,
3 fmt::{Debug, Display},
4 mem::ManuallyDrop,
5 ops::{Deref, DerefMut},
6};
7
8pub struct StaticTypeForStd<T, F = fn() -> T> {
13 val: UnsafeCell<Option<T>>,
14 is_init_lock: spin::Mutex<bool>,
15 call_fun: UnsafeCell<ManuallyDrop<F>>,
16}
17
18impl<T, F: FnOnce() -> T> StaticTypeForStd<T, F> {
19 pub const fn new(init_fun: F) -> StaticTypeForStd<T, F> {
22 Self {
23 val: UnsafeCell::new(None),
24 is_init_lock: spin::Mutex::new(false),
25 call_fun: UnsafeCell::new(ManuallyDrop::new(init_fun)),
26 }
27 }
28
29 pub fn init_static(&self) {
32 let mut lock = self.is_init_lock.lock();
33 if !*lock {
34 unsafe {
35 let f = ManuallyDrop::take(&mut *self.call_fun.get());
36 *self.val.get() = Some(f());
37 }
38 *lock = true;
39 } else {
40 }
42 }
43}
44
45impl<T, F> StaticTypeForStd<T, F> {
46 #[must_use]
49 pub fn is_init(&self) -> bool {
50 *self.is_init_lock.lock()
51 }
52
53 #[inline(always)]
57 pub fn get_static(&self) -> Option<&T> {
58 unsafe { &*self.val.get() }.as_ref()
59 }
60
61 #[inline(always)]
65 pub fn get_static_unchecked(&self) -> &T {
66 self.get_static().unwrap_or_else(|| {
67 unreachable!("StaticType not set value, Please is use static_val.init()")
68 })
69 }
70
71 #[inline(always)]
75 pub fn get_mut(&self) -> &mut Option<T> {
76 unsafe { &mut *self.val.get() }
77 }
78
79 #[inline(always)]
82 pub fn get_safe(&self) -> Option<&T> {
83 if !*self.is_init_lock.lock() {
84 return None;
85 }
86 unsafe { &*self.val.get() }.as_ref()
87 }
88
89 pub fn force_drop(&self) -> Option<T> {
94 *self.is_init_lock.lock() = false;
95 self.get_mut().take()
96 }
97}
98
99impl<T, F> Deref for StaticTypeForStd<T, F> {
100 type Target = T;
101 fn deref(&self) -> &Self::Target {
102 self.get_static_unchecked()
103 }
104}
105
106impl<T, F: FnOnce() -> T> DerefMut for StaticTypeForStd<T, F> {
108 fn deref_mut(&mut self) -> &mut Self::Target {
109 self.get_mut()
110 .as_mut()
111 .unwrap_or_else(|| unreachable!("StaticType not set"))
112 }
113}
114
115impl<T, F> AsRef<T> for StaticTypeForStd<T, F> {
116 fn as_ref(&self) -> &T {
117 self.get_static_unchecked()
118 }
119}
120
121unsafe impl<T, F> Send for StaticTypeForStd<T, F> {}
124unsafe impl<T, F> Sync for StaticTypeForStd<T, F> {}
125
126impl<T: Debug, F: FnOnce() -> T> Debug for StaticTypeForStd<T, F> {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 let val = self.get_static_unchecked();
129 f.write_fmt(format_args!("{val:?}"))
130 }
131}
132
133impl<T: Display, F> Display for StaticTypeForStd<T, F> {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 let val = self.get_static().map(|x| format!("{x}"));
136 let val = val.unwrap_or_else(|| "None".to_string());
137 f.write_str(&val)
138 }
139}
140
141#[test]
142fn test_static_type() {
143 static STATIC_TYPE: StaticTypeForStd<i32> = StaticTypeForStd::new(|| {
145 let r = 11 + 11;
146 println!("init_fun: {}", r);
147 r
148 });
149
150 assert_eq!(format!("{}", STATIC_TYPE), "None");
152
153 assert_eq!(STATIC_TYPE.is_init(), false);
155 STATIC_TYPE.init_static();
159
160 STATIC_TYPE.init_static();
162
163 assert_eq!(format!("{}", STATIC_TYPE), "22");
165
166 assert_eq!(*STATIC_TYPE, 22);
168}