pen_ffi/
arc.rs

1mod arc_block;
2mod arc_buffer;
3
4use arc_block::*;
5pub use arc_buffer::*;
6use core::{
7    alloc::Layout,
8    borrow::Borrow,
9    fmt::{self, Debug, Display, Formatter},
10    marker::PhantomData,
11    ops::Deref,
12    ptr::write,
13};
14
15#[repr(C)]
16pub struct Arc<T> {
17    block: ArcBlock,
18    phantom: PhantomData<T>,
19}
20
21impl<T> Arc<T> {
22    pub fn new(payload: T) -> Self {
23        let mut block = ArcBlock::new(Layout::new::<T>());
24
25        unsafe { write(block.ptr_mut() as *mut T, payload) };
26
27        Self {
28            block,
29            phantom: PhantomData,
30        }
31    }
32
33    pub fn get_mut(this: &mut Self) -> Option<&mut T> {
34        this.block
35            .get_mut()
36            .map(|pointer| unsafe { &mut *(pointer as *mut T) })
37    }
38
39    pub fn synchronize(self) {
40        self.block.synchronize()
41    }
42}
43
44impl<T> From<T> for Arc<T> {
45    fn from(payload: T) -> Self {
46        Self::new(payload)
47    }
48}
49
50impl<T> Deref for Arc<T> {
51    type Target = T;
52
53    fn deref(&self) -> &T {
54        unsafe { &*(self.block.ptr() as *const T) }
55    }
56}
57
58impl<T> AsRef<T> for Arc<T> {
59    fn as_ref(&self) -> &T {
60        self.deref()
61    }
62}
63
64impl<T> Borrow<T> for Arc<T> {
65    fn borrow(&self) -> &T {
66        self.deref()
67    }
68}
69
70impl<T> Clone for Arc<T> {
71    fn clone(&self) -> Self {
72        Self {
73            block: self.block.clone(),
74            phantom: PhantomData,
75        }
76    }
77}
78
79impl<T> Drop for Arc<T> {
80    fn drop(&mut self) {
81        self.block.drop::<T>();
82    }
83}
84
85impl<T: Default> Default for Arc<T> {
86    fn default() -> Self {
87        Self::new(T::default())
88    }
89}
90
91impl<T: Debug> Debug for Arc<T> {
92    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
93        write!(formatter, "{:?}", self.as_ref())
94    }
95}
96
97impl<T: Display> Display for Arc<T> {
98    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
99        write!(formatter, "{}", self.as_ref())
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106    use alloc::boxed::Box;
107    use core::mem::{drop, forget};
108
109    #[test]
110    fn create() {
111        Arc::new(0);
112    }
113
114    #[test]
115    fn clone() {
116        let arc = Arc::new(0);
117        drop(arc.clone());
118        drop(arc);
119    }
120
121    #[test]
122    fn new_box() {
123        forget(Arc::new(Box::new(0)));
124    }
125
126    #[test]
127    fn clone_box() {
128        let x = Arc::new(Box::new(0));
129        forget(x.clone());
130        forget(x);
131    }
132
133    #[test]
134    fn drop_box() {
135        Arc::new(Box::new(0));
136    }
137
138    #[test]
139    fn load_payload() {
140        assert_eq!(*Arc::new(42), 42);
141    }
142
143    mod zero_sized {
144        use super::*;
145
146        #[test]
147        fn create() {
148            Arc::new(());
149        }
150
151        #[test]
152        fn clone() {
153            let arc = Arc::new(());
154            drop(arc.clone());
155            drop(arc);
156        }
157
158        #[test]
159        #[allow(clippy::unit_cmp)]
160        fn load_payload() {
161            assert_eq!(*Arc::new(()), ());
162        }
163    }
164
165    fn drop_send_and_sync(_: impl Send + Sync) {}
166
167    #[test]
168    fn implement_send_and_sync() {
169        drop_send_and_sync(Arc::new(()));
170    }
171
172    #[test]
173    fn get_mut() {
174        let mut arc = Arc::new(0);
175
176        *Arc::get_mut(&mut arc).unwrap() = 42;
177
178        assert_eq!(*arc, 42);
179    }
180}