dynamic_pooling/
object.rs

1use crate::{
2	pool::{Pool, PoolInner},
3	reset::Reset,
4};
5use alloc::sync::{Arc, Weak};
6use core::{
7	borrow::{Borrow, BorrowMut},
8	cmp::Ordering,
9	fmt::{self, Debug, Display},
10	hash::{Hash, Hasher},
11	ops::{Deref, DerefMut},
12};
13
14/// An object taken from a [`Pool`].
15///
16/// When dropped, it will be [`Reset`] and returned to the pool if it has spare capacity.
17pub struct Pooled<T: Default + Reset> {
18	pool_inner: Weak<PoolInner<T>>,
19
20	// (internal docs, users don't need to worry about this)
21	/// ⚠️ If you set this to [`None`], you must ensure that the [`Pooled`] cannot be used anymore.
22	///
23	/// Almost all methods (including dereferencing) assume this is [`Some`], and they'll panic
24	/// otherwise.
25	object: Option<T>,
26}
27
28impl<T: Default + Reset> Pooled<T> {
29	pub(super) fn new(object: T, pool: &Pool<T>) -> Self {
30		Self {
31			object: Some(object),
32			pool_inner: Arc::downgrade(&pool.inner),
33		}
34	}
35
36	/// Detach this object from the pool.
37	///
38	/// It will not be returned to the pool once dropped.
39	///
40	/// ```
41	/// # use dynamic_pooling::{Pool, Pooled};
42	/// let pool: Pool<String> = Pool::new(69);
43	/// let foo: Pooled<String> = pool.take();
44	/// assert_eq!(pool.in_use(), 1);
45	///
46	/// let foo: String = Pooled::detach(foo);
47	/// assert_eq!(pool.in_use(), 0);
48	/// ```
49	pub fn detach(mut this: Self) -> T {
50		this.object.take().expect("always some")
51	}
52
53	/// Get the pool associated with this object.
54	///
55	/// Objects can outlive the pool they came from, so this returns an [`Option`].
56	///
57	/// ```
58	/// # use dynamic_pooling::{Pool, Pooled};
59	/// let pool = Pool::<String>::new(69);
60	/// let foo = pool.take();
61	/// assert!(Pooled::get_pool(&foo).is_some());
62	/// drop(pool);
63	/// assert!(Pooled::get_pool(&foo).is_none());
64	/// ```
65	pub fn get_pool(this: &Self) -> Option<Pool<T>> {
66		this.pool_inner.upgrade().map(|inner| Pool { inner })
67	}
68}
69
70impl<T: Default + Reset> Drop for Pooled<T> {
71	fn drop(&mut self) {
72		if let Some(pool_inner) = self.pool_inner.upgrade() {
73			if let Some(mut object) = self.object.take() {
74				object.reset();
75				let _ = pool_inner.push(object);
76			}
77		}
78	}
79}
80
81impl<T: Default + Reset> Deref for Pooled<T> {
82	type Target = T;
83	fn deref(&self) -> &Self::Target {
84		self.object.as_ref().expect("always some")
85	}
86}
87
88impl<T: Default + Reset> DerefMut for Pooled<T> {
89	fn deref_mut(&mut self) -> &mut Self::Target {
90		self.object.as_mut().expect("always some")
91	}
92}
93
94impl<T: Default + Reset> AsRef<T> for Pooled<T> {
95	fn as_ref(&self) -> &T {
96		self
97	}
98}
99
100impl<T: Default + Reset> AsMut<T> for Pooled<T> {
101	fn as_mut(&mut self) -> &mut T {
102		self
103	}
104}
105
106impl<T: Default + Reset> Borrow<T> for Pooled<T> {
107	fn borrow(&self) -> &T {
108		self
109	}
110}
111
112impl<T: Default + Reset> BorrowMut<T> for Pooled<T> {
113	fn borrow_mut(&mut self) -> &mut T {
114		self
115	}
116}
117
118impl<T: Default + Reset> Hash for Pooled<T>
119where
120	T: Hash,
121{
122	fn hash<H: Hasher>(&self, state: &mut H) {
123		(**self).hash(state);
124	}
125}
126
127impl<T: Default + Reset> PartialEq for Pooled<T>
128where
129	T: PartialEq<T>,
130{
131	fn eq(&self, other: &Self) -> bool {
132		(**self).eq(other)
133	}
134}
135
136impl<T: Default + Reset> PartialEq<T> for Pooled<T>
137where
138	T: PartialEq<T>,
139{
140	fn eq(&self, other: &T) -> bool {
141		(**self).eq(other)
142	}
143}
144
145impl<T: Default + Reset> Eq for Pooled<T> where T: Eq {}
146
147impl<T: Default + Reset> PartialOrd for Pooled<T>
148where
149	T: PartialOrd<T>,
150{
151	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
152		(**self).partial_cmp(other)
153	}
154}
155
156impl<T: Default + Reset> Ord for Pooled<T>
157where
158	T: Ord,
159{
160	fn cmp(&self, other: &Self) -> Ordering {
161		(**self).cmp(other)
162	}
163}
164
165impl<T: Default + Reset + PartialOrd<T>> PartialOrd<T> for Pooled<T> {
166	fn partial_cmp(&self, other: &T) -> Option<Ordering> {
167		(**self).partial_cmp(other)
168	}
169}
170
171impl<T: Default + Reset> Debug for Pooled<T>
172where
173	T: Debug,
174{
175	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176		(**self).fmt(f)
177	}
178}
179
180impl<T: Default + Reset> Display for Pooled<T>
181where
182	T: Display,
183{
184	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185		(**self).fmt(f)
186	}
187}