refs/main_lock/
main_lock.rs1#![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 #[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}