refs/
own.rs

1use std::{
2    fmt::{Debug, Formatter},
3    marker::Unsize,
4    ops::{CoerceUnsized, Deref, DerefMut},
5    ptr,
6};
7
8use crate::{Address, AsAny, Weak, ref_counter::RefCounter};
9
10pub(crate) type Stamp = u64;
11pub(crate) type Addr = usize;
12
13pub struct Own<T: ?Sized> {
14    bx:        Box<T>,
15    stamp:     Stamp,
16    type_name: &'static str,
17}
18
19unsafe impl<T: ?Sized> Send for Own<T> {}
20unsafe impl<T: ?Sized> Sync for Own<T> {}
21
22pub(crate) fn stamp() -> Stamp {
23    let now = instant::Instant::now();
24    u64::try_from(now.elapsed().as_millis()).expect("Failed to convert stamp")
25}
26
27impl<T: Sized + 'static> Own<T> {
28    pub fn new(val: T) -> Self {
29        let stamp = stamp();
30
31        let type_name = std::any::type_name::<T>();
32
33        #[cfg(feature = "stats")]
34        crate::stats::adjust_stat(type_name, 1);
35
36        let val = Box::new(val);
37        let address = val.deref().address();
38
39        assert_ne!(address, 1, "Invalid address. In cou be a closure or empty type.");
40
41        RefCounter::add(address, stamp);
42
43        Self {
44            bx: val,
45            stamp,
46            type_name,
47        }
48    }
49}
50
51impl<T: ?Sized + AsAny> Own<T> {
52    pub fn downcast<U: 'static>(&self) -> Option<Weak<U>> {
53        self.weak().downcast()
54    }
55}
56
57impl<T: ?Sized> Own<T> {
58    #[cfg(feature = "checks")]
59    fn check() {
60        assert!(
61            crate::is_main_thread(),
62            "Unsafe Own pointer deref: {}. Thread is not Main. Thread id: {}",
63            std::any::type_name::<T>(),
64            crate::current_thread_id()
65        );
66    }
67}
68
69impl<T: ?Sized> Own<T> {
70    pub fn addr(&self) -> usize {
71        self.bx.as_ref().address()
72    }
73}
74
75impl<T: ?Sized> Drop for Own<T> {
76    fn drop(&mut self) {
77        #[cfg(feature = "stats")]
78        crate::stats::adjust_stat(self.type_name, -1);
79        RefCounter::remove(self.addr());
80    }
81}
82
83impl<T: ?Sized> Deref for Own<T> {
84    type Target = T;
85    fn deref(&self) -> &T {
86        self.bx.deref()
87    }
88}
89
90impl<T: ?Sized> DerefMut for Own<T> {
91    fn deref_mut(&mut self) -> &mut Self::Target {
92        #[cfg(feature = "checks")]
93        Self::check();
94        self.bx.deref_mut()
95    }
96}
97
98impl<T: ?Sized> Own<T> {
99    pub fn weak(&self) -> Weak<T> {
100        Weak {
101            ptr:       ptr::from_ref(self.bx.deref()).cast_mut(),
102            stamp:     self.stamp,
103            type_name: self.type_name,
104        }
105    }
106}
107
108impl<T: Default + Sized + 'static> Default for Own<T> {
109    fn default() -> Self {
110        Self::new(T::default())
111    }
112}
113
114impl<T: ?Sized + Debug> Debug for Own<T> {
115    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
116        self.deref().fmt(f)
117    }
118}
119
120impl<T: ?Sized + PartialEq> PartialEq for Own<T> {
121    fn eq(&self, other: &Self) -> bool {
122        self.deref().eq(other.deref())
123    }
124}
125
126impl<T: ?Sized + PartialEq> PartialEq<T> for Own<T> {
127    fn eq(&self, other: &T) -> bool {
128        self.deref().eq(other)
129    }
130}
131
132impl<T, U> CoerceUnsized<Own<U>> for Own<T>
133where
134    T: Unsize<U> + ?Sized,
135    U: ?Sized,
136{
137}
138
139#[cfg(test)]
140mod tests {
141    use std::{
142        ops::{Deref, DerefMut},
143        sync::atomic::{AtomicU64, Ordering},
144        thread::spawn,
145    };
146
147    use serial_test::serial;
148
149    use crate::{Own, set_current_thread_as_main};
150
151    #[test]
152    fn deref() {
153        let num = Own::new(5);
154        assert_eq!(num.deref(), &5);
155        assert_eq!(num.weak().deref(), &5);
156    }
157
158    #[test]
159    #[should_panic(expected = "Invalid address. In cou be a closure or empty type.")]
160    fn own_from_closure() {
161        let _ = Own::new(|| {});
162    }
163
164    #[test]
165    #[serial]
166    fn deref_mut() {
167        set_current_thread_as_main();
168        let mut num = Own::new(5);
169        *num = 10;
170        assert_eq!(num.deref(), &10);
171        assert_eq!(num.weak().deref_mut(), &10);
172    }
173
174    #[test]
175    #[serial]
176    #[should_panic]
177    fn deref_async() {
178        set_current_thread_as_main();
179        let mut num = Own::new(5);
180        spawn(move || {
181            assert_eq!(num.deref_mut(), &5);
182        })
183        .join()
184        .unwrap();
185    }
186
187    #[test]
188    #[should_panic(expected = "Defererencing already freed weak pointer: i32")]
189    fn deref_freed() {
190        let num = Own::new(5);
191        let weak = num.weak();
192        drop(num);
193        dbg!(weak);
194    }
195
196    static VAL: AtomicU64 = AtomicU64::new(0);
197
198    #[test]
199    fn check_drop() {
200        struct ToDrop {
201            _a: bool,
202        }
203
204        impl Drop for ToDrop {
205            fn drop(&mut self) {
206                VAL.store(20, Ordering::Relaxed);
207            }
208        }
209
210        assert_eq!(VAL.load(Ordering::Relaxed), 0);
211
212        let num = Own::new(ToDrop { _a: false });
213        let weak = num.weak();
214        assert!(!weak.is_null());
215        drop(num);
216        assert!(weak.is_null());
217
218        assert_eq!(VAL.load(Ordering::Relaxed), 20);
219    }
220
221    #[test]
222    fn misc() {
223        let five = Own::new(5);
224        let ten = Own::new(10);
225        let another_five = Own::new(5);
226        let five_int = 5;
227
228        assert_eq!(five, another_five);
229        assert_ne!(five, ten);
230        assert_eq!(five, 5);
231        assert_ne!(five, 10);
232        assert_eq!("5", &format!("{five:?}"));
233        assert_eq!(five, five_int);
234    }
235}