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 pub fn new(pool: &RawPool<Self>, v: T) -> Self {
89 let mut t = pool.take();
90 *Self::get_mut(&mut t).unwrap() = v;
92 t
93 }
94
95 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());