1use parking_lot::Mutex;
2use std::collections::VecDeque;
3use std::fmt::{self, Debug};
4use std::sync::Arc;
5
6pub struct ObjectPool<T> {
9 available: Mutex<VecDeque<T>>,
11
12 create_fn: Arc<dyn Fn() -> T + Send + Sync>,
14
15 max_size: usize,
17}
18
19impl<T: std::fmt::Debug> std::fmt::Debug for ObjectPool<T> {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 f.debug_struct("ObjectPool")
22 .field("available", &self.available)
23 .field("max_size", &self.max_size)
24 .field("create_fn", &"<function>")
25 .finish()
26 }
27}
28
29impl<T> ObjectPool<T> {
31 fn return_object(&self, object: T) {
35 let mut available = self.available.lock();
36 if available.len() < self.max_size {
37 available.push_back(object);
38 }
39 }
41}
42
43impl<T: Send + 'static> ObjectPool<T> {
45 #[must_use]
57 pub fn new<F>(initial_size: usize, max_size: usize, create_fn: F) -> Self
58 where
59 F: Fn() -> T + Send + Sync + 'static,
60 {
61 let create_fn = Arc::new(create_fn);
62 let factory = Arc::clone(&create_fn);
63
64 let mut available = VecDeque::with_capacity(max_size);
66 for _ in 0..initial_size {
67 available.push_back((factory)());
68 }
69
70 Self {
71 available: Mutex::new(available),
72 create_fn,
73 max_size,
74 }
75 }
76
77 pub fn get(&self) -> PooledObject<'_, T> {
84 let object = {
85 let mut available = self.available.lock();
86 available.pop_front().unwrap_or_else(|| (self.create_fn)())
87 };
88
89 PooledObject {
90 object: Some(object),
91 pool: self,
92 }
93 }
94}
95
96pub struct PooledObject<'a, T> {
100 object: Option<T>,
102
103 pool: &'a ObjectPool<T>,
105}
106
107impl<T> PooledObject<'_, T> {
108 pub fn return_to_pool(mut self) {
111 if let Some(object) = self.object.take() {
112 self.pool.return_object(object);
113 }
114 }
115}
116
117impl<T> Drop for PooledObject<'_, T> {
118 fn drop(&mut self) {
119 if let Some(object) = self.object.take() {
120 self.pool.return_object(object);
121 }
122 }
123}
124
125impl<T> std::ops::Deref for PooledObject<'_, T> {
126 type Target = T;
127
128 fn deref(&self) -> &Self::Target {
129 self.object
130 .as_ref()
131 .expect("Object already returned to pool")
132 }
133}
134
135impl<T> std::ops::DerefMut for PooledObject<'_, T> {
136 fn deref_mut(&mut self) -> &mut Self::Target {
137 self.object
138 .as_mut()
139 .expect("Object already returned to pool")
140 }
141}
142
143impl<T: Debug> Debug for PooledObject<'_, T> {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 f.debug_struct("PooledObject")
146 .field("object", &self.object)
147 .finish()
148 }
149}
150
151#[derive(Debug)]
153pub struct StringPool {
154 inner: ObjectPool<String>,
156}
157
158impl StringPool {
159 #[must_use]
161 pub fn new(initial_size: usize, max_size: usize, initial_capacity: usize) -> Self {
162 Self {
163 inner: ObjectPool::new(initial_size, max_size, move || {
164 String::with_capacity(initial_capacity)
165 }),
166 }
167 }
168
169 pub fn get(&self) -> PooledString<'_> {
171 let mut string = self.inner.get();
172 string.clear(); PooledString(string)
174 }
175
176 pub fn get_with_value<S: AsRef<str>>(&self, value: S) -> PooledString<'_> {
178 let mut string = self.inner.get();
179 string.clear(); string.push_str(value.as_ref());
181 PooledString(string)
182 }
183}
184
185pub struct PooledString<'a>(PooledObject<'a, String>);
187
188impl PooledString<'_> {
189 pub fn return_to_pool(self) {
191 self.0.return_to_pool();
192 }
193}
194
195impl std::ops::Deref for PooledString<'_> {
196 type Target = String;
197
198 fn deref(&self) -> &Self::Target {
199 &self.0
200 }
201}
202
203impl std::ops::DerefMut for PooledString<'_> {
204 fn deref_mut(&mut self) -> &mut Self::Target {
205 &mut self.0
206 }
207}
208
209impl Debug for PooledString<'_> {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 Debug::fmt(&**self, f)
212 }
213}
214
215impl fmt::Display for PooledString<'_> {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 fmt::Display::fmt(&**self, f)
219 }
220}
221
222pub struct VecPool<T> {
224 inner: ObjectPool<Vec<T>>,
226}
227
228impl<T: Send + 'static> VecPool<T> {
229 #[must_use]
231 pub fn new(initial_size: usize, max_size: usize, initial_capacity: usize) -> Self {
232 Self {
233 inner: ObjectPool::new(initial_size, max_size, move || {
234 Vec::with_capacity(initial_capacity)
235 }),
236 }
237 }
238
239 pub fn get(&self) -> PooledVec<'_, T> {
241 let mut vec = self.inner.get();
242 vec.clear(); PooledVec(vec)
244 }
245}
246
247pub struct PooledVec<'a, T>(PooledObject<'a, Vec<T>>);
249
250impl<T> PooledVec<'_, T> {
251 pub fn return_to_pool(self) {
253 self.0.return_to_pool();
254 }
255}
256
257impl<T> std::ops::Deref for PooledVec<'_, T> {
258 type Target = Vec<T>;
259
260 fn deref(&self) -> &Self::Target {
261 &self.0
262 }
263}
264
265impl<T> std::ops::DerefMut for PooledVec<'_, T> {
266 fn deref_mut(&mut self) -> &mut Self::Target {
267 &mut self.0
268 }
269}
270
271impl<T: Debug> Debug for PooledVec<'_, T> {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 Debug::fmt(&**self, f)
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn test_object_pool() {
283 let pool = ObjectPool::new(5, 10, || String::from("test"));
284
285 let mut obj1 = pool.get();
287 assert_eq!(*obj1, "test");
288
289 obj1.push_str("-modified");
291 assert_eq!(*obj1, "test-modified");
292
293 drop(obj1);
295
296 let mut obj2 = pool.get();
300 assert_eq!(*obj2, "test");
301
302 obj2.push_str("-new");
304 assert_eq!(*obj2, "test-new");
305 }
306
307 #[test]
308 fn test_string_pool() {
309 let pool = StringPool::new(5, 10, 32);
310
311 let mut str1 = pool.get();
313 str1.push_str("hello");
314 assert_eq!(*str1, "hello");
315
316 drop(str1);
318
319 let str2 = pool.get();
321 assert_eq!(*str2, "");
322
323 let str3 = pool.get_with_value("world");
325 assert_eq!(*str3, "world");
326 }
327
328 #[test]
329 fn test_vec_pool() {
330 let pool = VecPool::new(5, 10, 32);
331
332 let mut vec1 = pool.get();
334 vec1.push(1);
335 vec1.push(2);
336 assert_eq!(*vec1, vec![1, 2]);
337
338 drop(vec1);
340
341 let vec2 = pool.get();
343 assert_eq!(*vec2, Vec::<i32>::new());
344 }
345}