poolshark/
arc.rs

1use super::{Poolable, RawPool, RawPoolable, WeakPool};
2use core::fmt;
3use std::{cmp::Eq, fmt::Debug, hash::Hash, mem::ManuallyDrop, ops::Deref, ptr};
4
5macro_rules! impl_arc {
6    ($name:ident, $inner:ident, $uniq:expr) => {
7        #[derive(Clone)]
8        pub struct $name<T: Poolable + Send + Sync + 'static> {
9            inner: ManuallyDrop<$inner<(WeakPool<Self>, T)>>,
10        }
11
12        unsafe impl<T: Poolable + Send + Sync + 'static> RawPoolable for $name<T> {
13            fn empty(pool: super::WeakPool<Self>) -> Self {
14                Self {
15                    inner: ManuallyDrop::new($inner::new((pool, T::empty()))),
16                }
17            }
18
19            fn capacity(&self) -> usize {
20                1
21            }
22
23            fn reset(&mut self) {
24                $inner::get_mut(&mut self.inner).unwrap().1.reset()
25            }
26
27            fn really_drop(self) {
28                let mut t = ManuallyDrop::new(self);
29                unsafe { ManuallyDrop::drop(&mut t.inner) }
30            }
31        }
32
33        impl<T: Poolable + Send + Sync + 'static> Drop for $name<T> {
34            fn drop(&mut self) {
35                if !$uniq(&mut self.inner) {
36                    unsafe { ManuallyDrop::drop(&mut self.inner) }
37                } else {
38                    match self.inner.0.upgrade() {
39                        None => unsafe { ManuallyDrop::drop(&mut self.inner) },
40                        Some(pool) => pool.insert(unsafe { ptr::read(self) }),
41                    }
42                }
43            }
44        }
45
46        impl<T: Poolable + Send + Sync + 'static> Deref for $name<T> {
47            type Target = T;
48
49            fn deref(&self) -> &Self::Target {
50                &self.inner.1
51            }
52        }
53
54        impl<T: Poolable + Debug + Send + Sync + 'static> fmt::Debug for $name<T> {
55            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56                self.inner.1.fmt(f)
57            }
58        }
59
60        impl<T: Poolable + PartialEq + Send + Sync + 'static> PartialEq for $name<T> {
61            fn eq(&self, other: &Self) -> bool {
62                self.inner.1 == other.inner.1
63            }
64        }
65
66        impl<T: Poolable + Eq + Send + Sync + 'static> Eq for $name<T> {}
67
68        impl<T: Poolable + PartialOrd + Send + Sync + 'static> PartialOrd for $name<T> {
69            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
70                self.inner.1.partial_cmp(&other.inner.1)
71            }
72        }
73
74        impl<T: Poolable + Ord + Send + Sync + 'static> Ord for $name<T> {
75            fn cmp(&self, other: &Self) -> std::cmp::Ordering {
76                self.inner.1.cmp(&other.inner.1)
77            }
78        }
79
80        impl<T: Poolable + Hash + Send + Sync + 'static> Hash for $name<T> {
81            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
82                self.inner.1.hash(state)
83            }
84        }
85
86        impl<T: Poolable + Send + Sync + 'static> $name<T> {
87            /// allocate a new arc from the specified pool and return it containing v
88            pub fn new(pool: &RawPool<Self>, v: T) -> Self {
89                let mut t = pool.take();
90                // values in the pool are guaranteed to be unique
91                *Self::get_mut(&mut t).unwrap() = v;
92                t
93            }
94
95            /// if the Arc is unique, get a mutable pointer to the inner T,
96            /// otherwise return None
97            pub fn get_mut(&mut self) -> Option<&mut T> {
98                match $inner::get_mut(&mut *self.inner) {
99                    Some((_, t)) => Some(t),
100                    None => None,
101                }
102            }
103
104            pub fn strong_count(&self) -> usize {
105                $inner::strong_count(&*self.inner)
106            }
107
108            pub fn as_ptr(&self) -> *const (WeakPool<Self>, T) {
109                $inner::as_ptr(&*self.inner)
110            }
111        }
112    };
113}
114
115#[cfg(feature = "triomphe")]
116use triomphe::Arc as TArcInner;
117
118#[cfg(feature = "triomphe")]
119impl_arc!(TArc, TArcInner, TArcInner::is_unique);
120
121#[cfg(feature = "triomphe")]
122impl<T: Poolable + Send + Sync + 'static> TArc<T> {
123    pub fn is_unique(&self) -> bool {
124        self.inner.is_unique()
125    }
126}
127
128use std::sync::Arc as ArcInner;
129impl_arc!(Arc, ArcInner, |a| ArcInner::get_mut(a).is_some());