fast_able/
static_type_std.rs

1use std::{
2    cell::UnsafeCell,
3    fmt::{Debug, Display},
4    mem::ManuallyDrop,
5    ops::{Deref, DerefMut},
6};
7
8/// must use `init`
9/// please at program start before use this fn
10pub struct StaticTypeForStd<T, F = fn() -> T> {
11    val: UnsafeCell<Option<T>>,
12    is_init_lock: spin::Mutex<bool>,
13    call_fun: UnsafeCell<ManuallyDrop<F>>,
14}
15
16impl<T, F: FnOnce() -> T> StaticTypeForStd<T, F> {
17    pub const fn new(init_fun: F) -> StaticTypeForStd<T, F> {
18        Self {
19            val: UnsafeCell::new(None),
20            is_init_lock: spin::Mutex::new(false),
21            call_fun: UnsafeCell::new(ManuallyDrop::new(init_fun)),
22        }
23    }
24
25    pub fn init_static(&self) {
26        let mut lock = self.is_init_lock.lock();
27        if !*lock {
28            unsafe {
29                let f = ManuallyDrop::take(&mut *self.call_fun.get());
30                *self.val.get() = Some(f());
31            }
32            *lock = true;
33        } else {
34            // warn!("StaticType is already initialized");
35        }
36    }
37}
38
39impl<T, F> StaticTypeForStd<T, F> {
40    #[must_use]
41    pub fn is_init(&self) -> bool {
42        *self.is_init_lock.lock()
43    }
44
45    /// this fn not safed; please before use this fn must use `init_static`
46    #[inline(always)]
47    pub fn get_static(&self) -> Option<&T> {
48        unsafe { &*self.val.get() }.as_ref()
49    }
50
51    /// this fn not safed; please before use this fn must use `init_call` or `get_or_init`
52    #[inline(always)]
53    pub fn get_static_unchecked(&self) -> &T {
54        self.get_static().unwrap_or_else(|| {
55            unreachable!("StaticType not set value, Please is use static_val.init()")
56        })
57    }
58
59    /// this fn not safed; please before use this fn must use `init_call` or `get_or_init`
60    #[inline(always)]
61    pub fn get_mut(&self) -> &mut Option<T> {
62        unsafe { &mut *self.val.get() }
63    }
64
65    #[inline(always)]
66    pub fn get_safe(&self) -> Option<&T> {
67        if !*self.is_init_lock.lock() {
68            return None;
69        }
70        unsafe { &*self.val.get() }.as_ref()
71    }
72
73    // 强制drop内存, 请确保在此时没有使用此内存
74    // force drop memory, please ensure that the memory is not used before this
75    pub fn force_drop(&self) -> Option<T> {
76        *self.is_init_lock.lock() = false;
77        self.get_mut().take()
78    }
79}
80
81impl<T, F> Deref for StaticTypeForStd<T, F> {
82    type Target = T;
83    fn deref(&self) -> &Self::Target {
84        self.get_static_unchecked()
85    }
86}
87
88// impl derefmut
89impl<T, F: FnOnce() -> T> DerefMut for StaticTypeForStd<T, F> {
90    fn deref_mut(&mut self) -> &mut Self::Target {
91        self.get_mut()
92            .as_mut()
93            .unwrap_or_else(|| unreachable!("StaticType not set"))
94    }
95}
96
97impl<T, F> AsRef<T> for StaticTypeForStd<T, F> {
98    fn as_ref(&self) -> &T {
99        self.get_static_unchecked()
100    }
101}
102
103// impl send and sync
104// focer thread safe
105unsafe impl<T, F> Send for StaticTypeForStd<T, F> {}
106unsafe impl<T, F> Sync for StaticTypeForStd<T, F> {}
107
108impl<T: Debug, F: FnOnce() -> T> Debug for StaticTypeForStd<T, F> {
109    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110        let val = self.get_static_unchecked();
111        f.write_fmt(format_args!("{val:?}"))
112    }
113}
114
115impl<T: Display, F> Display for StaticTypeForStd<T, F> {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        let val = self.get_static().map(|x| format!("{x}"));
118        let val = val.unwrap_or_else(|| "None".to_string());
119        f.write_str(&val)
120    }
121}
122
123#[test]
124fn test_static_type() {
125    //定义静态变量
126    static STATIC_TYPE: StaticTypeForStd<i32> = StaticTypeForStd::new(|| {
127        let r = 11 + 11;
128        println!("init_fun: {}", r);
129        r
130    });
131
132    // 没有初始化之前
133    assert_eq!(format!("{}", STATIC_TYPE), "None");
134
135    // panic
136    assert_eq!(STATIC_TYPE.is_init(), false);
137    // assert_eq!(*STATIC_TYPE, 22); //panic
138
139    // 初始化数据
140    STATIC_TYPE.init_static();
141
142    // 第二次初始化数据, 预期不执行
143    STATIC_TYPE.init_static();
144
145    // 控制台输出相应的数据
146    assert_eq!(format!("{}", STATIC_TYPE), "22");
147
148    // 获取数据,数据相同
149    assert_eq!(*STATIC_TYPE, 22);
150}