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