archery/shared_pointer/kind/arc/
mod.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 */
5
6use crate::shared_pointer::kind::SharedPointerKind;
7use alloc::boxed::Box;
8use alloc::sync::Arc;
9use core::fmt;
10use core::fmt::Debug;
11use core::fmt::Formatter;
12use core::mem;
13use core::mem::ManuallyDrop;
14use core::ops::Deref;
15use core::ops::DerefMut;
16use core::ptr;
17
18type UntypedArc = Arc<()>;
19
20/// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for
21/// [`Arc`] pointers.
22pub struct ArcK {
23    /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as
24    /// [`Arc<T>`](alloc::sync::Arc).  Not sure if it can be dropped as [`UntypedArc`], but it
25    /// seems to be playing with fire (even more than we already are).
26    inner: ManuallyDrop<UntypedArc>,
27}
28
29impl ArcK {
30    #[inline(always)]
31    fn new_from_inner<T>(arc: Arc<T>) -> ArcK {
32        ArcK { inner: ManuallyDrop::new(unsafe { mem::transmute::<Arc<T>, UntypedArc>(arc) }) }
33    }
34
35    #[inline(always)]
36    unsafe fn take_inner<T>(self) -> Arc<T> {
37        let arc: UntypedArc = ManuallyDrop::into_inner(self.inner);
38
39        mem::transmute(arc)
40    }
41
42    #[inline(always)]
43    unsafe fn as_inner_ref<T>(&self) -> &Arc<T> {
44        let arc_t: *const Arc<T> =
45            (self.inner.deref() as *const UntypedArc).cast::<alloc::sync::Arc<T>>();
46
47        // Static check to make sure we are not messing up the sizes.
48        // This could happen if we allowed for `T` to be unsized, because it would need to be
49        // represented as a wide pointer inside `Arc`.
50        // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21
51        //      gets fixed
52        let _ = mem::transmute::<UntypedArc, Arc<T>>;
53
54        &*arc_t
55    }
56
57    #[inline(always)]
58    unsafe fn as_inner_mut<T>(&mut self) -> &mut Arc<T> {
59        let arc_t: *mut Arc<T> =
60            (self.inner.deref_mut() as *mut UntypedArc).cast::<alloc::sync::Arc<T>>();
61
62        &mut *arc_t
63    }
64}
65
66unsafe impl SharedPointerKind for ArcK {
67    #[inline(always)]
68    fn new<T>(v: T) -> ArcK {
69        ArcK::new_from_inner(Arc::new(v))
70    }
71
72    #[inline(always)]
73    fn from_box<T>(v: Box<T>) -> ArcK {
74        ArcK::new_from_inner::<T>(Arc::from(v))
75    }
76
77    #[inline(always)]
78    unsafe fn as_ptr<T>(&self) -> *const T {
79        Arc::as_ptr(self.as_inner_ref())
80    }
81
82    #[inline(always)]
83    unsafe fn deref<T>(&self) -> &T {
84        self.as_inner_ref::<T>().as_ref()
85    }
86
87    #[inline(always)]
88    unsafe fn try_unwrap<T>(self) -> Result<T, ArcK> {
89        Arc::try_unwrap(self.take_inner()).map_err(ArcK::new_from_inner)
90    }
91
92    #[inline(always)]
93    unsafe fn get_mut<T>(&mut self) -> Option<&mut T> {
94        Arc::get_mut(self.as_inner_mut())
95    }
96
97    #[inline(always)]
98    unsafe fn make_mut<T: Clone>(&mut self) -> &mut T {
99        Arc::make_mut(self.as_inner_mut())
100    }
101
102    #[inline(always)]
103    unsafe fn strong_count<T>(&self) -> usize {
104        Arc::strong_count(self.as_inner_ref::<T>())
105    }
106
107    #[inline(always)]
108    unsafe fn clone<T>(&self) -> ArcK {
109        ArcK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) }
110    }
111
112    #[inline(always)]
113    unsafe fn drop<T>(&mut self) {
114        ptr::drop_in_place::<Arc<T>>(self.as_inner_mut());
115    }
116}
117
118impl Debug for ArcK {
119    #[inline(always)]
120    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
121        f.write_str("ArcK")
122    }
123}
124
125#[cfg(test)]
126mod test;