refs/main_lock/
main_lock.rs

1#![allow(clippy::mut_from_ref)]
2
3use std::{cell::UnsafeCell, ops::Deref};
4
5use crate::assert_main_thread;
6
7#[derive(Default)]
8pub struct MainLock<T: Default> {
9    val: UnsafeCell<Option<T>>,
10}
11
12unsafe impl<T: Default> Send for MainLock<T> {}
13unsafe impl<T: Default> Sync for MainLock<T> {}
14
15impl<T: Default> MainLock<T> {
16    pub const fn new() -> Self {
17        Self {
18            val: UnsafeCell::new(None),
19        }
20    }
21
22    pub fn get_or_init(&self, init: impl Fn() -> T) -> &mut T {
23        assert_main_thread();
24
25        let rf = unsafe { self.val.get().as_mut().unwrap() };
26
27        if rf.is_none() {
28            *rf = Some(init());
29        }
30
31        rf.as_mut().unwrap()
32    }
33
34    pub fn get_mut(&self) -> &mut T {
35        self.get_or_init(|| T::default())
36    }
37
38    pub fn set(&self, value: T) -> &mut T {
39        assert_main_thread();
40        let rf = unsafe { self.val.get().as_mut().unwrap() };
41        *rf = Some(value);
42        rf.as_mut().unwrap()
43    }
44
45    /// # Safety
46    ///
47    /// Caller must ensure that this call is performed on main thread
48    /// and that walue was already initialized
49    #[allow(clippy::mut_from_ref)]
50    pub unsafe fn get_unchecked(&self) -> &mut T {
51        unsafe { self.val.get().as_mut().unwrap().as_mut().unwrap() }
52    }
53}
54
55impl<T: Default + 'static> Deref for MainLock<T> {
56    type Target = T;
57
58    fn deref(&self) -> &Self::Target {
59        self.get_mut()
60    }
61}