est_render/utils/
arcref.rs

1use std::{cell::RefCell, sync::Arc};
2
3#[cfg(any(debug_assertions, feature = "enable-release-validation"))]
4use std::time::{Duration, Instant};
5
6/// Custom ArcRef type that wraps a Arc with RefCell without
7/// Making it difficult to type.
8// #[derive(Clone)]
9pub struct ArcRef<T> {
10    inner: Arc<RefCell<T>>,
11}
12
13impl<T> ArcRef<T> {
14    /// Create a new ArcRef with the given value.
15    pub fn new(value: T) -> ArcRef<T> {
16        ArcRef {
17            inner: Arc::new(RefCell::new(value)),
18        }
19    }
20
21    /// Creata a clone of the ArcRef. This will atomically increment the reference count.
22    pub fn clone(&self) -> ArcRef<T> {
23        ArcRef {
24            inner: self.inner.clone(),
25        }
26    }
27
28    /// Borrow the value immutably. This will atomically increment the reference count.
29    /// If the value is already borrowed mutably, this will block until the mutable borrow is released.
30    /// NOTE: In debug mode, this will panic if the value is already borrowed immutably for more than 5 seconds.
31    pub fn wait_borrow(&self) -> std::cell::Ref<T> {
32        #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
33        let start = Instant::now();
34
35        loop {
36            if let Ok(borrow) = self.inner.try_borrow() {
37                return borrow;
38            }
39
40            #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
41            if start.elapsed() > Duration::from_secs(5) {
42                panic!("wait_borrow: waited more than 5 seconds to acquire immutable borrow");
43            }
44        }
45    }
46
47    /// Borrow the value mutably. This will atomically increment the reference count.
48    /// If the value is already borrowed, this will block until the borrow is released.
49    /// NOTE: In debug mode, this will panic if the value is already borrowed mutably for more than 5 seconds.
50    pub fn wait_borrow_mut(&self) -> std::cell::RefMut<T> {
51        #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
52        let start = Instant::now();
53
54        loop {
55            if let Ok(borrow) = self.inner.try_borrow_mut() {
56                return borrow;
57            }
58
59            #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
60            if start.elapsed() > Duration::from_secs(5) {
61                panic!("wait_borrow_mut: waited more than 5 seconds to acquire mutable borrow");
62            }
63        }
64    }
65
66    /// Try to borrow the value immutably. This will atomically increment the reference count.
67    /// Will panic if the value is already borrowed mutably.
68    pub fn borrow(&self) -> std::cell::Ref<T> {
69        self.inner.borrow()
70    }
71
72    /// Try to borrow the value mutably. This will atomically increment the reference count.
73    /// Will panic if the value is already borrowed.
74    pub fn borrow_mut(&self) -> std::cell::RefMut<T> {
75        self.inner.borrow_mut()
76    }
77
78    /// Try to borrow the value immutably. This will atomically increment the reference count.
79    /// Will return None if the value is already borrowed mutably.
80    pub fn try_borrow(&self) -> Option<std::cell::Ref<T>> {
81        self.inner.try_borrow().ok()
82    }
83
84    /// Try to borrow the value mutably. This will atomically increment the reference count.
85    /// Will return None if the value is already borrowed.
86    pub fn try_borrow_mut(&self) -> Option<std::cell::RefMut<T>> {
87        self.inner.try_borrow_mut().ok()
88    }
89
90    /// Try to unwrap the ArcRef. This will return the inner value if there are no other references to it.
91    /// If there are other references, this will return the ArcRef itself as an error.
92    pub fn try_unwrap(self) -> Result<T, Self> {
93        let refcelled = Arc::try_unwrap(self.inner).map_err(|arc| ArcRef { inner: arc })?;
94
95        let inner = refcelled.into_inner();
96        Ok(inner)
97    }
98
99    pub fn ptr_eq(&self, other: &Self) -> bool {
100        Arc::ptr_eq(&self.inner, &other.inner)
101    }
102
103    pub fn as_ptr(_self: &Self) -> *const T {
104        Arc::as_ptr(&_self.inner) as *const T
105    }
106}
107
108pub mod hasher {
109    use super::ArcRef;
110    use std::hash::Hash;
111    use std::sync::Arc;
112
113    impl<T: std::hash::Hash> Hash for ArcRef<T> {
114        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
115            Arc::as_ptr(&self.inner).hash(state);
116        }
117    }
118}
119
120impl<T> std::fmt::Debug for ArcRef<T> {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        f.debug_struct("ArcRef").finish()
123    }
124}
125
126impl<T> Clone for ArcRef<T> {
127    fn clone(&self) -> Self {
128        Self {
129            inner: self.inner.clone(),
130        }
131    }
132}
133
134impl<T: PartialEq> PartialEq for ArcRef<T> {
135    fn eq(&self, other: &Self) -> bool {
136        Arc::ptr_eq(&self.inner, &other.inner)
137    }
138}
139
140impl<T: PartialEq> Eq for ArcRef<T> {}