generic_pool/lib.rs
1//! A pool for recycling allocated objects for later reuse. Uses generic get/put methods so you can store (almost) any type in a single pool instance.
2//!
3//! The main advantage of this library compared to other pools is that it can store and retrieve an __abritrary__ number of __different objects__ seemlessly.
4//! The pool itself does not contain any generics, only the get und put methods do. You initialise the pool and add any object to it that you want to recycle,
5//! and when you need them later on you just tell the pool which type of object you want. The internal implementation does all the magic of selecting the correct
6//! object type.
7//!
8//! This library is 100% pure Rust, uses no unstable or nighly only features and, most importantly, does not contain any unsafe code.
9//! It also has zero dependencies on default, but has an optional serde feature which enables
10//! de-/serialization of the configuration by [Serde](https://docs.serde.rs/serde/).
11//!
12//! ## Features
13//!
14//! - Provides a lightweigth __regular version__ as well as a thread-save __sync version__.
15//! - Does optionally provide a __drop guard__ which will automatically add objects back to the store after they go out of scope.
16//! - Allows configuring the maximum number of stored objects to prevent RAM exhaustion.
17//! - Allows configuring the rate at which the internal capacity gets increased over time.
18//! - Each configuration option can be set for each object type individually.
19//! - You can also set a fallback configuration for object types for which no constum configuration was set.
20//! - Provides optional auto-creation of objects which implement the [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) trait.
21//! - Offers cheap [`Clon`](https://doc.rust-lang.org/std/clone/trait.Clone.html)ing, so you can easily use the same pool in many places.
22//!
23//! ## A quick example
24//!
25//! This example demonstrates the most basic usage. We define two different structs, `Person` and `Animal`.
26//! We insert both of them into the pool and retrieve them later on. Note that the pool ensures that the correct object type gets returned.
27//!
28//! ```rust
29//! use generic_pool::Pool;
30//!
31//! #[derive(Debug, Default, Clone, Eq, PartialEq)]
32//! struct Person {
33//! name: String,
34//! age: i32,
35//! }
36//!
37//! #[derive(Debug, Default, Clone, Eq, PartialEq)]
38//! struct Animal {
39//! home: bool,
40//! name: String,
41//! age_in_month: u64,
42//! }
43//!
44//! fn main() {
45//! // Initialize the pool. Note that there is no need to specify any generic type parameters.
46//! let mut pool = Pool::new();
47//!
48//! let p = Person {
49//! name: String::from("Mark"),
50//! age: 100,
51//! };
52//!
53//! let a = Animal {
54//! home: true,
55//! name: String::from("Meow"),
56//! age_in_month: 12,
57//! };
58//!
59//! // Add copies of the objects to the pool. Note that the pool takes any object.
60//! pool.put(p.clone());
61//! pool.put(a.clone());
62//!
63//! // Retrieve the objects from the pool.
64//! let person: Person = pool.get().unwrap(); // Returns `Option<Person>`.
65//! let animal: Animal = pool.get_or_default(); // Returns `Animal`, but requires `Animal` to implement Default.
66//!
67//! // The objects we retrieve are exactly the ones we put into the pool earlier.
68//! assert_eq!(person, p);
69//! assert_eq!(animal, a);
70//!
71//! // NOTE: You should implement some kind of reset logic for objects saved in the pool.
72//! // E.g.: person.reset()
73//! }
74//! ```
75//! ## Security
76//!
77//! The pool does not modify the objects it receives or gives out in any way, and does thus in particular not reset objects properly.
78//! __It is your responsibility to reset objects as appropriate either before adding them back to the store, or after receiving them.__
79//! Otherwise you will likely open up security holes by accidentaly using data from earlier operations.
80//!
81//! ### A common bad example
82//!
83//! Many frontend APIs do also provide priviledged access if they receive the proper credentials. Depending on the implementation the admin flag
84//! might only get explicitly set if some special credentials are send over. Without resetting the admin flag of recycled request objects this can
85//! open up a big security hole.
86//!
87//! ```ignore
88//! use generic_pool::Pool;
89//!
90//! struct FrontendRequest {
91//! admin_credentials: Option<String>,
92//! commands: Vec<String>,
93//! }
94//!
95//! #[derive(Default)]
96//! struct BackendRequest {
97//! is_admin: bool,
98//! commands: Vec<Command>,
99//! }
100//!
101//! fn main() {
102//! let mut pool = Pool::new();
103//!
104//! /* initialize API... */
105//!
106//! loop {
107//! // Retrieve a frontend request.
108//! let frontend_req: FrontendRequest = get_frontend_req();
109//!
110//! // Retrieve a recycled backend request object from the pool.
111//! let mut backend_req = pool.get_or_default_with_guard::<BackendRequest>();
112//!
113//! /* HAZARD - The backend request object might still contain older commands. */
114//!
115//! // Parse the commands and check if they are known and valid.
116//! for cmd in frountend_req.commands.iter() {
117//! match parse_cmd(cmd) {
118//! Ok(parsed_cmd) => backend_req.commands.push(parsed_cmd),
119//! Err(err) => return_error_to_client_and_abort(err),
120//! }
121//! }
122//!
123//! /* HAZARD - the backend request might still have the admin flag set!!! */
124//!
125//! if let Some(credentials) = &frontend_req.admin_credentials {
126//! match check_admin_credentials(credentials) {
127//! Ok(_) => backend_req.is_admin = true,
128//! Err(err) => return_error_to_client_and_abort(err),
129//! }
130//! }
131//!
132//! // The backend might now receive unintended commands or even commands
133//! // from unpriviledged users with the admin flag set.
134//! send_backend_request(backend_req);
135//!
136//! // NOTE: The drop guard of the backend request will put it back into the pool now.
137//! }
138//! }
139//! ```
140//!
141//! ### The solution
142//!
143//! Of course a simple solution would be the implement the whole parsing and checking process in such a way that all fields of any recycled object get always filled
144//! with entirely new data, but this might not always be favorable. It can be difficult to check that all fields from all objects you recycle are overwritten before being used.
145//!
146//! The most secure solution is thus to write some explicit resetting logic for all objects you use and to make sure it gets called whenever you retrieve an object
147//! from the pool.
148//!
149//! ```ignore
150//! use generic_pool::{Pool, DropGuard};
151//!
152//! /// A local trait providing the reset logic for all recycled objects.
153//! trait Reset {
154//! fn reset(self) -> Self; // See below why we use this pattern.
155//! }
156//!
157//! struct FrontendRequest {
158//! admin_credentials: Option<String>,
159//! commands: Vec<String>,
160//! }
161//!
162//! #[derive(Default)]
163//! struct BackendRequest {
164//! is_admin: bool,
165//! commands: Vec<Command>,
166//! }
167//!
168//! // We implement the trait on any drop guard by this.
169//! impl<G: AsMut<BackendRequest>> Reset for G {
170//! fn reset(mut self) -> Self {
171//! let req = self.as_mut();
172//! req.is_admin = false;
173//! req.commands.clear();
174//!
175//! self
176//! }
177//! }
178//!
179//! fn main() {
180//! let mut pool = Pool::new();
181//!
182//! /* initialize API... */
183//!
184//! loop {
185//! // Retrieve a frontend request.
186//! let frontend_req: FrontendRequest = get_frontend_req();
187//!
188//! // Retrieve a recycled backend request object from the pool.
189//! let mut backend_req = match pool.get_with_guard::<BackendRequest>() {
190//! Some(req) => req.reset(), // Is an expression, gives back req
191//! None => DropGuard::new(BackendRequest::default(), &pool), // No need to reset
192//! };
193//!
194//! /* We can proceed safely now */
195//! }
196//! }
197//! ```
198//!
199//! ## Configuration
200//!
201//! You can configure the maximum size of the stores internal buffers, as well as their initial size and the rate at which the capacity increases.
202//! These settings always apply to a specific type of object beeing stored in the pool, and never at
203//! the pool as a whole. That is if you store e.g. 2 different object types and configure a default
204//! maximum capacity of __1_000__, the pool will store up to __2_000__ objects. The settings are intended for limiting the memory usage of the pool.
205//!
206//! The pools fallback configuration will apply to all object types until you set a custom one for an object type. If you do not specify a costum
207//! fallback config for the pool, the pool will use the default values for [`Config`].
208//!
209//! ### Example
210//!
211//! ```rust
212//! use generic_pool::{Pool, Config};
213//!
214//! fn main() {
215//! // Use a non-default config.
216//! let config = Config {
217//! max: 1_000,
218//! step: 100,
219//! start: 500,
220//! };
221//!
222//! assert_ne!(config, Config::default());
223//!
224//! let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
225//!
226//! // Alternative:
227//! // let mut pool = Pool::new();
228//! // pool.set_fallback_config(config);
229//!
230//! assert_eq!(config, pool.fallback_config());
231//! assert_eq!(config, pool.get_config::<Vec<u8>>());
232//!
233//! // Create a costum config for `Vec<u8>`.
234//! let custom_config = Config {
235//! max: 100,
236//! step: 10,
237//! start: 10,
238//! };
239//!
240//! pool.set_config::<Vec<u8>>(custom_config);
241//!
242//! assert_eq!(custom_config, pool.get_config::<Vec<u8>>());
243//! }
244//! ```
245use std::collections::HashMap;
246use std::sync::{Arc, RwLock};
247use std::rc::Rc;
248use std::cell::RefCell;
249use std::any::{Any, TypeId};
250use std::ops::{Deref, DerefMut};
251use std::fmt;
252use std::hash::{Hash, Hasher};
253
254#[cfg(feature = "serde")]
255use serde::{Deserialize, Serialize};
256
257
258
259#[cfg(test)]
260mod tests;
261
262
263
264/// The configuration options of the pools internal store.
265///
266/// The settings always apply to a specific type of object beeing stored in the pool, and never at
267/// the pool as a whole. That is if you store e.g. 2 different object types and configure a default
268/// maximum capacity of __1_000__, the pool will store up to __2_000__ objects.
269/// The settings are intended for limiting the memory usage of the pool.
270///
271/// The pools fallback configuration will apply to all object types until you set a custom one for an object type.
272/// If you do not specify a costum fallback config for the pool, the pool will use the default values for [`Config`].
273///
274/// We allow setting a [`max`](#structfield.max) capacity of the internal pool buffer. If the buffer is full
275/// and another object gets added to the pool, the new object will get dropped.
276///
277/// If a certain buffer gets created, it will use the [`start`](#structfield.start) value to configure its
278/// initial capacity. Whenever the capacity is reached and its length has not yet reached the
279/// [`max`](#structfield.max) value, the [`step`](#structfield.step) value is used to determine by which amount
280/// the capacity should be increased. Note that it will use a lower value then [`step`](#structfield.step)
281/// if otherwise the capacity would exceed the [`max`](#structfield.max) value.
282///
283/// # Example
284///
285/// ```rust
286/// use generic_pool::{Pool, Config};
287///
288/// fn main() {
289/// // Use a non-default config.
290/// let config = Config {
291/// max: 1_000,
292/// step: 100,
293/// start: 500,
294/// };
295///
296/// assert_ne!(config, Config::default());
297///
298/// let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
299///
300/// // Alternative:
301/// // let mut pool = Pool::new();
302/// // pool.set_fallback_config(config);
303///
304/// assert_eq!(config, pool.fallback_config());
305/// assert_eq!(config, pool.get_config::<Vec<u8>>());
306///
307/// // Create a costum config for `Vec<u8>`.
308/// let custom_config = Config {
309/// max: 100,
310/// step: 10,
311/// start: 10,
312/// };
313///
314/// pool.set_config::<Vec<u8>>(custom_config);
315///
316/// assert_eq!(custom_config, pool.get_config::<Vec<u8>>());
317/// }
318/// ```
319#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
320#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
321pub struct Config {
322 /// The maximum number of elements of a specific type to be hold inside the pool.
323 ///
324 /// __Default__: 100_000
325 pub max: usize,
326 /// The initial capacity for the storage of elements of a specific type.
327 ///
328 /// __Default__: 1_000
329 pub start: usize,
330 /// How much capacity to add to the storage of elements of a specific type if the storage
331 /// is full and has not yet reached the maximum.
332 ///
333 /// __Default__: 1_000
334 pub step: usize,
335}
336
337impl Default for Config {
338 fn default() -> Self {
339 Self {
340 max: 100_000,
341 start: 1_000,
342 step: 1_000,
343 }
344 }
345}
346
347impl fmt::Display for Config {
348 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349 write!(f, "Config {{max: {}, start: {}, step: {}}})", self.max, self.start, self.step)
350 }
351}
352
353impl Config {
354 /// Determines if we need to increase the capacity, and if so, by which amount.
355 fn next_step(&self, current_capacity: usize) -> Option<usize> {
356 if current_capacity>=self.max {
357 return None;
358 }
359
360 let remaining = self.max-current_capacity;
361
362 if remaining>=self.step {
363 return Some(self.step);
364 } else {
365 return Some(remaining);
366 }
367 }
368
369 /// Allocates more space if necessary, and returns an empty error if the
370 /// storage is full.
371 fn allocate_as_necessary<T>(&self, store: &mut Vec<T>) -> Result<(), ()> {
372 if store.len()>=self.max {
373 return Err(()); // The store is already full.
374 }
375
376 let capacity = store.capacity();
377
378 if capacity==store.len() {
379 if let Some(step) = self.next_step(capacity) {
380 store.reserve(step);
381 }
382 }
383
384 Ok(())
385 }
386}
387
388
389/// A smart pointer which automatically puts the contained object back into the [`Pool`] on drop.
390///
391/// This version is not thread-safe. For the thread-safe version take a look at [`SyncDropGuard`].
392#[derive(Debug)]
393pub struct DropGuard<T: Any> {
394 inner: Option<T>,
395 pool: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
396}
397
398impl<T: Any + Clone> Clone for DropGuard<T> {
399 fn clone(&self) -> Self {
400 Self {
401 inner: Clone::clone(&self.inner),
402 pool: Rc::clone(&self.pool),
403 }
404 }
405}
406
407impl<T: Any + PartialEq> PartialEq for DropGuard<T> {
408 fn eq(&self, other: &DropGuard<T>) -> bool {
409 self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
410 }
411}
412
413impl<T: Any + Eq> Eq for DropGuard<T> {}
414
415impl<T: Any + PartialOrd> PartialOrd for DropGuard<T> {
416 fn partial_cmp(&self, other: &DropGuard<T>) -> Option<std::cmp::Ordering> {
417 self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
418 }
419}
420
421impl<T: Any + Ord> Ord for DropGuard<T> {
422 fn cmp(&self, other: &DropGuard<T>) -> std::cmp::Ordering {
423 self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
424 }
425}
426
427/// The hash value corresponds to the hash value of the contained object.
428impl<T: Any + Hash> Hash for DropGuard<T> {
429 fn hash<H: Hasher>(&self, state: &mut H) {
430 self.inner.as_ref().unwrap().hash(state);
431 }
432}
433
434impl<T: Any + fmt::Display> fmt::Display for DropGuard<T> {
435 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436 fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
437 }
438}
439
440impl<T: Any> DropGuard<T> {
441 /// Creates a new [`DropGuard`] from an abritrary object and adds the reference to a regular [`Pool`].
442 ///
443 /// # Example
444 ///
445 /// Creating a [`DropGuard`] yourself might be usefull if you want to use objects which
446 /// you want to manually create, but where you still want to have the auto-adding to the pool
447 /// once they go out of scope.
448 ///
449 /// ```rust
450 /// use generic_pool::{Pool, DropGuard};
451 ///
452 /// struct Buffer(Vec<u8>);
453 ///
454 /// impl Buffer {
455 /// fn len(&self) -> usize {
456 /// self.0.len()
457 /// }
458 /// }
459 ///
460 /// fn main() {
461 /// let mut pool = Pool::new();
462 ///
463 /// // You use buffers which have a length of exactly 1kb.
464 /// let buffer = match pool.get_with_guard::<Buffer>() {
465 /// Some(buffer) => buffer,
466 /// None => DropGuard::new(Buffer(vec![0u8; 1024]), &pool),
467 /// };
468 ///
469 /// assert_eq!(buffer.len(), 1024);
470 ///
471 /// assert!(pool.get::<Buffer>().is_none());
472 /// drop(buffer);
473 /// let buffer = pool.get::<Buffer>().unwrap();
474 /// assert_eq!(buffer.len(), 1024);
475 /// }
476 /// ```
477 pub fn new(obj: T, pool: &Pool) -> Self {
478 let inner = Some(obj);
479 let pool = Rc::clone(&pool.inner);
480 Self {
481 inner,
482 pool,
483 }
484 }
485
486 /// Consume this guard and return the contained object.
487 ///
488 /// Note that this is an associated function and not a method. See the example.
489 ///
490 /// # Example
491 ///
492 /// ```rust
493 /// use generic_pool::{Pool, DropGuard};
494 ///
495 /// struct Buffer(Vec<u8>);
496 ///
497 /// impl Buffer {
498 /// fn len(&self) -> usize {
499 /// self.0.len()
500 /// }
501 /// }
502 ///
503 /// fn main() {
504 /// let mut pool = Pool::new();
505 ///
506 /// // You use buffers which have a length of exactly 1kb.
507 /// let buffer = match pool.get_with_guard::<Buffer>() {
508 /// Some(buffer) => buffer,
509 /// None => DropGuard::new(Buffer(vec![0u8; 1024]), &pool),
510 /// };
511 ///
512 /// // Maybe you want to use the buffer for something else.
513 /// let buffer: Buffer = DropGuard::into_inner(buffer);
514 /// let mut buffer: Vec<u8> = buffer.0;
515 /// buffer.clear();
516 ///
517 /// assert_eq!(buffer.len(), 0);
518 /// }
519 /// ```
520 pub fn into_inner(mut guard: DropGuard<T>) -> T {
521 guard.inner.take().unwrap()
522 }
523}
524
525/// Ensures the contained value gets automatically added back to the [`Pool`] it came from.
526impl<T: Any> Drop for DropGuard<T> {
527 fn drop(&mut self) {
528 if let Some(obj) = self.inner.take() {
529 let obj = Box::new(obj);
530 if let Ok(mut pool) = self.pool.try_borrow_mut() {
531 pool.put::<T>(obj);
532 }
533 }
534 }
535}
536
537impl<T: Any> AsRef<T> for DropGuard<T> {
538 fn as_ref(&self) -> &T {
539 self.inner.as_ref().unwrap()
540 }
541}
542
543impl<T: Any> AsMut<T> for DropGuard<T> {
544 fn as_mut(&mut self) -> &mut T {
545 self.inner.as_mut().unwrap()
546 }
547}
548
549impl<T: Any> Deref for DropGuard<T> {
550 type Target = T;
551
552 fn deref(&self) -> &Self::Target {
553 self.as_ref()
554 }
555}
556
557impl<T: Any> DerefMut for DropGuard<T> {
558 fn deref_mut(&mut self) -> &mut Self::Target {
559 self.as_mut()
560 }
561}
562
563
564/// A smart pointer which automatically puts the contained object back into the [`SyncPool`] on drop.
565///
566/// This version is thread-safe. For the not thread-safe version take a look at [`DropGuard`].
567pub struct SyncDropGuard<T: Any + Send + Sync> {
568 inner: Option<T>,
569 pool: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
570}
571
572impl<T: Any + Send + Sync + Clone> Clone for SyncDropGuard<T> {
573 fn clone(&self) -> Self {
574 Self {
575 inner: Clone::clone(&self.inner),
576 pool: Arc::clone(&self.pool),
577 }
578 }
579}
580
581impl<T: Any + Send + Sync + PartialEq> PartialEq for SyncDropGuard<T> {
582 fn eq(&self, other: &SyncDropGuard<T>) -> bool {
583 self.inner.as_ref().unwrap().eq(other.inner.as_ref().unwrap())
584 }
585}
586
587impl<T: Any + Send + Sync + Eq> Eq for SyncDropGuard<T> {}
588
589impl<T: Any + Send + Sync + PartialOrd> PartialOrd for SyncDropGuard<T> {
590 fn partial_cmp(&self, other: &SyncDropGuard<T>) -> Option<std::cmp::Ordering> {
591 self.inner.as_ref().unwrap().partial_cmp(other.inner.as_ref().unwrap())
592 }
593}
594
595impl<T: Any + Send + Sync + Ord> Ord for SyncDropGuard<T> {
596 fn cmp(&self, other: &SyncDropGuard<T>) -> std::cmp::Ordering {
597 self.inner.as_ref().unwrap().cmp(other.inner.as_ref().unwrap())
598 }
599}
600
601/// The hash value corresponds to the hash value of the contained object.
602impl<T: Any + Send + Sync + Hash> Hash for SyncDropGuard<T> {
603 fn hash<H: Hasher>(&self, state: &mut H) {
604 self.inner.as_ref().unwrap().hash(state);
605 }
606}
607
608impl<T: Any + Send + Sync + fmt::Display> fmt::Display for SyncDropGuard<T> {
609 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610 fmt::Display::fmt(self.inner.as_ref().unwrap(), f)
611 }
612}
613
614impl<T: Any + Send + Sync> SyncDropGuard<T> {
615 /// Creates a new [`DropGuard`] from an abritrary object and adds the reference to a [`SyncPool`].
616 ///
617 /// # Example
618 ///
619 /// Creating a [`SyncDropGuard`] yourself might be usefull if you want to use objects which
620 /// you want to manually create, but where you still want to have the auto-adding to the pool
621 /// once they go out of scope.
622 ///
623 /// ```rust
624 /// use generic_pool::{SyncPool, SyncDropGuard};
625 ///
626 /// struct Buffer(Vec<u8>);
627 ///
628 /// impl Buffer {
629 /// fn len(&self) -> usize {
630 /// self.0.len()
631 /// }
632 /// }
633 ///
634 /// fn main() {
635 /// let mut pool = SyncPool::new();
636 ///
637 /// // You use buffers which have a length of exactly 1kb.
638 /// let buffer = match pool.get_with_guard::<Buffer>() {
639 /// Some(buffer) => buffer,
640 /// None => SyncDropGuard::new(Buffer(vec![0u8; 1024]), &pool),
641 /// };
642 ///
643 /// assert_eq!(buffer.len(), 1024);
644 ///
645 /// assert!(pool.get::<Buffer>().is_none());
646 /// drop(buffer);
647 /// let buffer = pool.get::<Buffer>().unwrap();
648 /// assert_eq!(buffer.len(), 1024);
649 /// }
650 /// ```
651 pub fn new(obj: T, pool: &SyncPool) -> Self {
652 let inner = Some(obj);
653 let pool = Arc::clone(&pool.inner);
654 Self {
655 inner,
656 pool,
657 }
658 }
659
660 /// Consume this guard and return the contained object.
661 ///
662 /// Note that this is an associated function and not a method. See the example.
663 ///
664 /// # Example
665 ///
666 /// ```rust
667 /// use generic_pool::{SyncPool, SyncDropGuard};
668 ///
669 /// struct Buffer(Vec<u8>);
670 ///
671 /// impl Buffer {
672 /// fn len(&self) -> usize {
673 /// self.0.len()
674 /// }
675 /// }
676 ///
677 /// fn main() {
678 /// let mut pool = SyncPool::new();
679 ///
680 /// // You use buffers which have a length of exactly 1kb.
681 /// let buffer = match pool.get_with_guard::<Buffer>() {
682 /// Some(buffer) => buffer,
683 /// None => SyncDropGuard::new(Buffer(vec![0u8; 1024]), &pool),
684 /// };
685 ///
686 /// // Maybe you want to use the buffer for something else.
687 /// let buffer: Buffer = SyncDropGuard::into_inner(buffer);
688 /// let mut buffer: Vec<u8> = buffer.0;
689 /// buffer.clear();
690 ///
691 /// assert_eq!(buffer.len(), 0);
692 /// }
693 /// ```
694 pub fn into_inner(mut guard: SyncDropGuard<T>) -> T {
695 guard.inner.take().unwrap()
696 }
697}
698
699/// Ensures the contained value gets automatically added back to the [`SyncPool`] it came from.
700impl<T: Any + Send + Sync> Drop for SyncDropGuard<T> {
701 fn drop(&mut self) {
702 if let Some(obj) = self.inner.take() {
703 let obj = Box::new(obj);
704 if let Ok(mut pool) = self.pool.write() {
705 pool.put::<T>(obj);
706 }
707 }
708 }
709}
710
711impl<T: Any + Send + Sync> AsRef<T> for SyncDropGuard<T> {
712 fn as_ref(&self) -> &T {
713 self.inner.as_ref().unwrap()
714 }
715}
716
717impl<T: Any + Send + Sync> AsMut<T> for SyncDropGuard<T> {
718 fn as_mut(&mut self) -> &mut T {
719 self.inner.as_mut().unwrap()
720 }
721}
722
723impl<T: Any + Send + Sync> Deref for SyncDropGuard<T> {
724 type Target = T;
725
726 fn deref(&self) -> &Self::Target {
727 self.as_ref()
728 }
729}
730
731impl<T: Any + Send + Sync> DerefMut for SyncDropGuard<T> {
732 fn deref_mut(&mut self) -> &mut Self::Target {
733 self.as_mut()
734 }
735}
736
737
738
739/// The internal structure for all pools we use. Contains all the magic implementation details.
740#[derive(Debug)]
741struct PoolInner<B> {
742 /// Contains the internal buffers, with each one holding one specific object type.
743 store: HashMap<TypeId, Vec<B>>,
744 /// Contains the custom configuration for each specific object type, if any.
745 config: HashMap<TypeId, Config>,
746 /// The default configuration for all object types which do not have a costum configuration.
747 fallback_config: Config,
748}
749
750impl<B> Default for PoolInner<B> {
751 fn default() -> Self {
752 Self {
753 store: HashMap::new(),
754 config: HashMap::new(),
755 fallback_config: Config::default(),
756 }
757 }
758}
759
760impl<B> fmt::Display for PoolInner<B> {
761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762 write!(
763 f, "{{store: {} entries, config: {} entries, fallback_config: {}}}",
764 self.store.len(), self.config.len(),
765 self.fallback_config.to_string(),
766 )
767 }
768}
769
770impl<B> PoolInner<B> {
771 /// Retrieve the configuration for a specific object type.
772 pub fn get_config<T: Any>(&self) -> Config {
773 let id = TypeId::of::<T>();
774
775 match self.config.get(&id) {
776 Some(config) => config.clone(),
777 None => self.fallback_config,
778 }
779 }
780
781 /// Retrieve the fallback configuration for all object types with no costum configuration set.
782 pub fn fallback_config(&self) -> Config {
783 self.fallback_config
784 }
785
786 /// Sets the costum configuration for a specific object type.
787 pub fn set_config<T: Any>(&mut self, config: Config) {
788 let id = TypeId::of::<T>();
789
790 self.config.insert(id, config);
791 }
792
793 /// Deletes the costum configuration of a specific object type.
794 pub fn delete_config<T: Any>(&mut self) {
795 let id = TypeId::of::<T>();
796
797 self.config.remove(&id);
798 }
799
800 /// Sets the fallback configuration for all object types with no costum configuration set.
801 pub fn set_fallback_config(&mut self, config: Config) {
802 self.fallback_config = config;
803 }
804
805 /// Tries to retrieve an instance of a specific object type from the internal buffer.
806 pub fn get<T: Any>(&mut self) -> Option<B> {
807 let id = TypeId::of::<T>();
808
809 if let Some(list) = self.store.get_mut(&id) {
810 return list.pop();
811 }
812
813 return None
814 }
815
816 /// Tries to add an instance of a specific object type into the internal buffer.
817 pub fn put<T: Any>(&mut self, boxed_obj: B) {
818 let id = TypeId::of::<T>();
819
820 let config = match self.config.get(&id) {
821 Some(config) => config,
822 None => &self.fallback_config,
823 };
824
825 match self.store.get_mut(&id) {
826 Some(list) => {
827 if let Ok(_) = config.allocate_as_necessary(list) {
828 list.push(boxed_obj);
829 }
830 }
831 None => {
832 let mut list = Vec::<B>::with_capacity(config.start);
833 list.push(boxed_obj);
834 self.store.insert(id, list);
835 }
836 }
837 }
838}
839
840
841
842/// A pool that allows storing abritrary objects.
843///
844/// This version is not thread-safe. For the thread-safe version take a look at [`SyncPool`].
845#[derive(Default)]
846pub struct Pool {
847 pub(crate) inner: Rc<RefCell<PoolInner<Box<dyn Any>>>>,
848}
849
850/// The cloned [`Pool`] will still point to the same instance.
851impl Clone for Pool {
852 fn clone(&self) -> Self {
853 Self {
854 inner: Rc::clone(&self.inner),
855 }
856 }
857}
858
859impl fmt::Display for Pool {
860 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
861 write!(f, "Pool {}", self.inner.borrow().to_string())
862 }
863}
864
865impl Pool {
866 /// Creates a new [`Pool`] with the default fallback configuration.
867 ///
868 /// # Example
869 /// ```rust
870 /// use generic_pool::{Pool, Config};
871 ///
872 /// fn main() {
873 /// let pool = Pool::new();
874 /// // Equivalent:
875 /// // let pool = Pool::default();
876 ///
877 /// assert_eq!(pool.fallback_config(), Config::default());
878 /// }
879 /// ```
880 pub fn new() -> Self {
881 Self::default()
882 }
883
884 /// Create a new [`Pool`] with the provided [`Config`] as the fallback configuration.
885 ///
886 /// # Example
887 /// ```rust
888 /// use generic_pool::{Pool, Config};
889 ///
890 /// fn main() {
891 /// // Use a non-default config.
892 /// let config = Config {
893 /// max: 1_000,
894 /// step: 100,
895 /// start: 500,
896 /// };
897 ///
898 /// assert_ne!(config, Config::default());
899 ///
900 /// let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
901 ///
902 /// assert_eq!(config, pool.fallback_config());
903 /// }
904 /// ```
905 pub fn with_fallback_config(config: Config) -> Self {
906 let mut pool = Self::default();
907 pool.set_fallback_config(config);
908
909 pool
910 }
911
912 /// Retrieve the currently active [`Config`] for the provided object type.
913 ///
914 /// If you have not manually set a [`Config`] for the provided object type, this method
915 /// will return the fallback configuration.
916 ///
917 /// # Example
918 /// ```rust
919 /// use generic_pool::{Pool, Config};
920 ///
921 /// fn main() {
922 /// let mut pool = Pool::new();
923 ///
924 /// let config = Config {
925 /// max: 1_000,
926 /// step: 100,
927 /// start: 500,
928 /// };
929 ///
930 /// // Set the config for `Vec<u8>`.
931 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
932 ///
933 /// // Retrieve the config for `Vec<u8>`.
934 /// // We would get back the fallback config without the line above.
935 /// let config_compare = pool.get_config::<Vec<u8>>();
936 ///
937 /// assert_eq!(config_compare, config);
938 /// assert_ne!(config_compare, pool.fallback_config());
939 /// }
940 /// ```
941 pub fn get_config<T: Any>(&self) -> Config {
942 self.inner.borrow().get_config::<T>()
943 }
944
945 /// Retrieve the fallback [`Config`] for all object types which do not have
946 /// a specific [`Config`] set.
947 ///
948 /// # Example
949 /// ```rust
950 /// use generic_pool::{Pool, Config};
951 ///
952 /// fn main() {
953 /// // Use a non-default config.
954 /// let config = Config {
955 /// max: 1_000,
956 /// step: 100,
957 /// start: 500,
958 /// };
959 ///
960 /// assert_ne!(config, Config::default());
961 ///
962 /// let mut pool = Pool::with_fallback_config(config); // NOTE Config implements Copy.
963 ///
964 /// assert_eq!(config, pool.fallback_config());
965 /// }
966 /// ```
967 pub fn fallback_config(&self) -> Config {
968 self.inner.borrow().fallback_config
969 }
970
971 /// Update the [`Config`] for the provided object type.
972 ///
973 /// # Example
974 /// ```rust
975 /// use generic_pool::{Pool, Config};
976 ///
977 /// fn main() {
978 /// let mut pool = Pool::new();
979 ///
980 /// let config = Config {
981 /// max: 1_000,
982 /// step: 100,
983 /// start: 500,
984 /// };
985 ///
986 /// // Set the config for `Vec<u8>`.
987 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
988 ///
989 /// // Retrieve the config for `Vec<u8>`.
990 /// // We would get back the fallback config without the line above.
991 /// let config_compare = pool.get_config::<Vec<u8>>();
992 ///
993 /// assert_eq!(config_compare, config);
994 /// assert_ne!(config_compare, pool.fallback_config());
995 /// }
996 /// ```
997 pub fn set_config<T: Any>(&mut self, config: Config) {
998 self.inner.borrow_mut().set_config::<T>(config);
999 }
1000
1001 /// Delete the costum [`Config`] for the provided object type.
1002 /// Afterwards the fallback config will apply again.
1003 ///
1004 /// # Example
1005 /// ```rust
1006 /// use generic_pool::{Pool, Config};
1007 ///
1008 /// fn main() {
1009 /// let mut pool = Pool::new();
1010 ///
1011 /// let config = Config {
1012 /// max: 1_000,
1013 /// step: 100,
1014 /// start: 500,
1015 /// };
1016 ///
1017 /// // Set the config for `Vec<u8>`.
1018 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1019 ///
1020 /// assert_eq!(pool.get_config::<Vec<u8>>(), config);
1021 ///
1022 /// // Delete the costum config. Afterwards the fallback config will apply.
1023 /// pool.delete_config::<Vec<u8>>();
1024 ///
1025 /// assert_ne!(pool.get_config::<Vec<u8>>(), config);
1026 /// assert_eq!(pool.get_config::<Vec<u8>>(), pool.fallback_config());
1027 /// }
1028 /// ```
1029 pub fn delete_config<T: Any>(&mut self) {
1030 self.inner.borrow_mut().delete_config::<T>();
1031 }
1032
1033 /// Set the fallback [`Config`] for all object types which do not have
1034 /// a specific [`Config`] set.
1035 ///
1036 /// # Example
1037 /// ```rust
1038 /// use generic_pool::{Pool, Config};
1039 ///
1040 /// fn main() {
1041 /// // Start with the default config.
1042 /// let mut pool = Pool::new();
1043 ///
1044 /// // Create a non-default config.
1045 /// let config = Config {
1046 /// max: 1_000,
1047 /// step: 100,
1048 /// start: 500,
1049 /// };
1050 ///
1051 /// assert_ne!(config, pool.fallback_config());
1052 ///
1053 /// pool.set_fallback_config(config);
1054 ///
1055 /// assert_eq!(config, pool.fallback_config());
1056 /// }
1057 /// ```
1058 pub fn set_fallback_config(&mut self, config: Config) {
1059 self.inner.borrow_mut().fallback_config = config;
1060 }
1061
1062 /// Try to retrieve an object of the specified type. Will give back `None` if the there are no
1063 /// objects of this type currently stored in the pool.
1064 ///
1065 /// # Example
1066 ///
1067 /// ```rust
1068 /// use generic_pool::Pool;
1069 ///
1070 /// fn main() {
1071 /// let mut pool = Pool::new();
1072 ///
1073 /// let buffer = match pool.get::<Vec<u8>>() {
1074 /// Some(mut buffer) => {
1075 /// buffer.clear();
1076 /// buffer
1077 /// }
1078 /// None => Vec::new(),
1079 /// };
1080 ///
1081 /// assert_eq!(buffer.len(), 0);
1082 /// }
1083 /// ```
1084 pub fn get<T: Any>(&mut self) -> Option<T> {
1085 if let Some(boxed_obj) = self.inner.borrow_mut().get::<T>() {
1086 if let Ok(element) = boxed_obj.downcast::<T>() {
1087 return Some(*element);
1088 }
1089 }
1090
1091 None
1092 }
1093
1094 /// Retrieve an object of the specified type. If there is no object of this type currently
1095 /// stored in the pool it will create one using its [`Default`] implementation.
1096 ///
1097 /// # Example
1098 ///
1099 /// ```rust
1100 /// use generic_pool::Pool;
1101 ///
1102 /// fn main() {
1103 /// let mut pool = Pool::new();
1104 ///
1105 /// let buffer = pool.get_or_default::<Vec<u8>>();
1106 ///
1107 /// assert_eq!(buffer.len(), 0);
1108 /// }
1109 /// ```
1110 pub fn get_or_default<T: Any + Default>(&mut self) -> T {
1111 match self.get::<T>() {
1112 Some(obj) => {
1113 return obj
1114 }
1115 None => {
1116 return T::default()
1117 }
1118 }
1119 }
1120
1121 /// Try to retrieve an object of the specified type with a drop guard. Will give back `None`
1122 /// if the there are no objects of this type currently stored in the pool.
1123 ///
1124 /// Once the returned [`DropGuard`] - if any - goes out of scope it will automatically put
1125 /// the contained object pack into the pool. Note that the object might still get dropped
1126 /// by the pool if the corresponding internal buffer is full.
1127 ///
1128 /// # Example
1129 ///
1130 /// ```rust
1131 /// use generic_pool::{Pool, DropGuard};
1132 ///
1133 /// fn main() {
1134 /// let mut pool = Pool::new();
1135 ///
1136 /// let buffer: DropGuard<Vec<u8>> = match pool.get_with_guard::<Vec<u8>>() {
1137 /// Some(mut buffer) => {
1138 /// // DropGuard is a smart pointer, so we can call Vec.clear() directly.
1139 /// buffer.clear();
1140 /// buffer
1141 /// }
1142 /// None => DropGuard::new(Vec::new(), &pool),
1143 /// };
1144 ///
1145 /// assert_eq!(buffer.len(), 0);
1146 ///
1147 /// assert!(pool.get::<Vec<u8>>().is_none());
1148 ///
1149 /// // Will put the buffer back into the pool.
1150 /// drop(buffer);
1151 ///
1152 /// assert!(pool.get::<Vec<u8>>().is_some());
1153 /// }
1154 /// ```
1155 pub fn get_with_guard<T: Any>(&mut self) -> Option<DropGuard<T>> {
1156 match self.get::<T>() {
1157 Some(obj) => Some(DropGuard::new(obj, self)),
1158 None => None,
1159 }
1160 }
1161
1162 /// Retrieve an object of the specified type with a drop guard. If there is no object of this type currently
1163 /// stored in the pool it will create one using its [`Default`] implementation.
1164 ///
1165 /// Once the returned [`DropGuard`] goes out of scope it will automatically put
1166 /// the contained object pack into the pool. Note that the object might still get dropped
1167 /// by the pool if the corresponding internal buffer is full.
1168 ///
1169 /// # Example
1170 ///
1171 /// ```rust
1172 /// use generic_pool::{Pool, DropGuard};
1173 ///
1174 /// fn main() {
1175 /// let mut pool = Pool::new();
1176 ///
1177 /// let buffer: DropGuard<Vec<u8>> = pool.get_or_default_with_guard::<Vec<u8>>();
1178 ///
1179 /// assert_eq!(buffer.len(), 0);
1180 ///
1181 /// assert!(pool.get::<Vec<u8>>().is_none());
1182 ///
1183 /// // Will put the buffer back into the pool.
1184 /// drop(buffer);
1185 ///
1186 /// assert!(pool.get::<Vec<u8>>().is_some());
1187 /// }
1188 /// ```
1189 pub fn get_or_default_with_guard<T: Any + Default>(&mut self) -> DropGuard<T> {
1190 let obj = self.get_or_default::<T>();
1191
1192 DropGuard::new(obj, self)
1193 }
1194
1195 /// Add an object to the pool. Unless the corresponding internal buffer is full, you can retrieve
1196 /// it later on by calling [`Pool.get()`](#method.get) or one of its variants.
1197 ///
1198 /// # Example
1199 ///
1200 /// ```rust
1201 /// use generic_pool::Pool;
1202 ///
1203 /// fn main() {
1204 /// let mut pool = Pool::new();
1205 ///
1206 /// assert!(pool.get::<Vec<u8>>().is_none());
1207 ///
1208 /// pool.put(vec![0u8; 1024]);
1209 ///
1210 /// let buffer = pool.get::<Vec<u8>>().unwrap();
1211 ///
1212 /// assert_eq!(buffer.len(), 1024);
1213 /// }
1214 /// ```
1215 pub fn put<T: Any>(&mut self, obj: T) {
1216 let obj = Box::new(obj);
1217 self.inner.borrow_mut().put::<T>(obj);
1218 }
1219}
1220
1221
1222/// A thread-safe pool that allows storing abritrary objects.
1223///
1224/// This version is thread-safe. For the not thread-safe version take a look at [`Pool`].
1225#[derive(Default)]
1226pub struct SyncPool {
1227 pub(crate) inner: Arc<RwLock<PoolInner<Box<dyn Any + Send + Sync>>>>,
1228}
1229
1230/// The cloned [`SyncPool`] will still point to the same instance.
1231impl Clone for SyncPool {
1232 fn clone(&self) -> Self {
1233 Self {
1234 inner: Arc::clone(&self.inner),
1235 }
1236 }
1237}
1238
1239impl fmt::Display for SyncPool {
1240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1241 write!(f, "SyncPool {}", self.inner.read().unwrap().to_string())
1242 }
1243}
1244
1245impl SyncPool {
1246 /// Creates a new [`SyncPool`] with the default fallback configuration.
1247 ///
1248 /// # Example
1249 /// ```rust
1250 /// use generic_pool::{SyncPool, Config};
1251 ///
1252 /// fn main() {
1253 /// let pool = SyncPool::new();
1254 /// // Equivalent:
1255 /// // let pool = SyncPool::default();
1256 ///
1257 /// assert_eq!(pool.fallback_config(), Config::default());
1258 /// }
1259 /// ```
1260 pub fn new() -> Self {
1261 Self::default()
1262 }
1263
1264 /// Create a new [`SyncPool`] with the provided [`Config`] as the fallback configuration.
1265 ///
1266 /// # Example
1267 /// ```rust
1268 /// use generic_pool::{SyncPool, Config};
1269 ///
1270 /// fn main() {
1271 /// // Use a non-default config.
1272 /// let config = Config {
1273 /// max: 1_000,
1274 /// step: 100,
1275 /// start: 500,
1276 /// };
1277 ///
1278 /// assert_ne!(config, Config::default());
1279 ///
1280 /// let mut pool = SyncPool::with_fallback_config(config); // NOTE Config implements Copy.
1281 ///
1282 /// assert_eq!(config, pool.fallback_config());
1283 /// }
1284 /// ```
1285 pub fn with_fallback_config(config: Config) -> Self {
1286 let mut pool = Self::default();
1287 pool.set_fallback_config(config);
1288
1289 pool
1290 }
1291
1292 /// Retrieve the currently active [`Config`] for the provided object type.
1293 ///
1294 /// If you have not manually set a [`Config`] for the provided object type, this method
1295 /// will return the fallback configuration.
1296 ///
1297 /// # Example
1298 /// ```rust
1299 /// use generic_pool::{SyncPool, Config};
1300 ///
1301 /// fn main() {
1302 /// let mut pool = SyncPool::new();
1303 ///
1304 /// let config = Config {
1305 /// max: 1_000,
1306 /// step: 100,
1307 /// start: 500,
1308 /// };
1309 ///
1310 /// // Set the config for `Vec<u8>`.
1311 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1312 ///
1313 /// // Retrieve the config for `Vec<u8>`.
1314 /// // We would get back the fallback config without the line above.
1315 /// let config_compare = pool.get_config::<Vec<u8>>();
1316 ///
1317 /// assert_eq!(config_compare, config);
1318 /// assert_ne!(config_compare, pool.fallback_config());
1319 /// }
1320 /// ```
1321 pub fn get_config<T: Any + Send + Sync>(&mut self) -> Config {
1322 let inner = self.inner.read().unwrap();
1323 inner.get_config::<T>()
1324 }
1325
1326 /// Retrieve the fallback [`Config`] for all object types which do not have
1327 /// a specific [`Config`] set.
1328 ///
1329 /// # Example
1330 /// ```rust
1331 /// use generic_pool::{SyncPool, Config};
1332 ///
1333 /// fn main() {
1334 /// // Use a non-default config.
1335 /// let config = Config {
1336 /// max: 1_000,
1337 /// step: 100,
1338 /// start: 500,
1339 /// };
1340 ///
1341 /// assert_ne!(config, Config::default());
1342 ///
1343 /// let mut pool = SyncPool::with_fallback_config(config); // NOTE Config implements Copy.
1344 ///
1345 /// assert_eq!(config, pool.fallback_config());
1346 /// }
1347 /// ```
1348 pub fn fallback_config(&self) -> Config {
1349 let inner = self.inner.read().unwrap();
1350 inner.fallback_config()
1351 }
1352
1353 /// Update the [`Config`] for the provided object type.
1354 ///
1355 /// # Example
1356 /// ```rust
1357 /// use generic_pool::{SyncPool, Config};
1358 ///
1359 /// fn main() {
1360 /// let mut pool = SyncPool::new();
1361 ///
1362 /// let config = Config {
1363 /// max: 1_000,
1364 /// step: 100,
1365 /// start: 500,
1366 /// };
1367 ///
1368 /// // Set the config for `Vec<u8>`.
1369 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1370 ///
1371 /// // Retrieve the config for `Vec<u8>`.
1372 /// // We would get back the fallback config without the line above.
1373 /// let config_compare = pool.get_config::<Vec<u8>>();
1374 ///
1375 /// assert_eq!(config_compare, config);
1376 /// assert_ne!(config_compare, pool.fallback_config());
1377 /// }
1378 /// ```
1379 pub fn set_config<T: Any + Send + Sync>(&mut self, config: Config) {
1380 let mut inner = self.inner.write().unwrap();
1381 inner.set_config::<T>(config);
1382 }
1383
1384 /// Delete the costum [`Config`] for the provided object type.
1385 /// Afterwards the fallback config will apply again.
1386 ///
1387 /// # Example
1388 /// ```rust
1389 /// use generic_pool::{SyncPool, Config};
1390 ///
1391 /// fn main() {
1392 /// let mut pool = SyncPool::new();
1393 ///
1394 /// let config = Config {
1395 /// max: 1_000,
1396 /// step: 100,
1397 /// start: 500,
1398 /// };
1399 ///
1400 /// // Set the config for `Vec<u8>`.
1401 /// pool.set_config::<Vec<u8>>(config); // NOTE: Config implements Copy.
1402 ///
1403 /// assert_eq!(pool.get_config::<Vec<u8>>(), config);
1404 ///
1405 /// // Delete the costum config. Afterwards the fallback config will apply.
1406 /// pool.delete_config::<Vec<u8>>();
1407 ///
1408 /// assert_ne!(pool.get_config::<Vec<u8>>(), config);
1409 /// assert_eq!(pool.get_config::<Vec<u8>>(), pool.fallback_config());
1410 /// }
1411 /// ```
1412 pub fn delete_config<T: Any>(&mut self) {
1413 let mut inner = self.inner.write().unwrap();
1414 inner.delete_config::<T>();
1415 }
1416
1417 /// Set the fallback [`Config`] for all object types which do not have
1418 /// a specific [`Config`] set.
1419 ///
1420 /// # Example
1421 /// ```rust
1422 /// use generic_pool::{SyncPool, Config};
1423 ///
1424 /// fn main() {
1425 /// // Start with the default config.
1426 /// let mut pool = SyncPool::new();
1427 ///
1428 /// // Create a non-default config.
1429 /// let config = Config {
1430 /// max: 1_000,
1431 /// step: 100,
1432 /// start: 500,
1433 /// };
1434 ///
1435 /// assert_ne!(config, pool.fallback_config());
1436 ///
1437 /// pool.set_fallback_config(config);
1438 ///
1439 /// assert_eq!(config, pool.fallback_config());
1440 /// }
1441 /// ```
1442 pub fn set_fallback_config(&mut self, config: Config) {
1443 let mut inner = self.inner.write().unwrap();
1444 inner.set_fallback_config(config);
1445 }
1446
1447 /// Try to retrieve an object of the specified type. Will give back `None` if the there are no
1448 /// objects of this type currently stored in the pool.
1449 ///
1450 /// # Example
1451 ///
1452 /// ```rust
1453 /// use generic_pool::SyncPool;
1454 ///
1455 /// fn main() {
1456 /// let mut pool = SyncPool::new();
1457 ///
1458 /// let buffer = match pool.get::<Vec<u8>>() {
1459 /// Some(mut buffer) => {
1460 /// buffer.clear();
1461 /// buffer
1462 /// }
1463 /// None => Vec::new(),
1464 /// };
1465 ///
1466 /// assert_eq!(buffer.len(), 0);
1467 /// }
1468 /// ```
1469 pub fn get<T: Any + Send + Sync>(&self) -> Option<T> {
1470 let mut inner = self.inner.write().unwrap();
1471 if let Some(boxed_obj) = inner.get::<T>() {
1472 if let Ok(element) = boxed_obj.downcast::<T>() {
1473 return Some(*element);
1474 }
1475 }
1476
1477 None
1478 }
1479
1480 /// Retrieve an object of the specified type. If there is no object of this type currently
1481 /// stored in the pool it will create one using its [`Default`] implementation.
1482 ///
1483 /// # Example
1484 ///
1485 /// ```rust
1486 /// use generic_pool::SyncPool;
1487 ///
1488 /// fn main() {
1489 /// let mut pool = SyncPool::new();
1490 ///
1491 /// let buffer = pool.get_or_default::<Vec<u8>>();
1492 ///
1493 /// assert_eq!(buffer.len(), 0);
1494 /// }
1495 /// ```
1496 pub fn get_or_default<T: Any + Send + Sync + Default>(&self) -> T {
1497 match self.get::<T>() {
1498 Some(obj) => {
1499 return obj
1500 }
1501 None => {
1502 return T::default()
1503 }
1504 }
1505 }
1506
1507 /// Try to retrieve an object of the specified type with a drop guard. Will give back `None`
1508 /// if the there are no objects of this type currently stored in the pool.
1509 ///
1510 /// Once the returned [`SyncDropGuard`] - if any - goes out of scope it will automatically put
1511 /// the contained object pack into the pool. Note that the object might still get dropped
1512 /// by the pool if the corresponding internal buffer is full.
1513 ///
1514 /// # Example
1515 ///
1516 /// ```rust
1517 /// use generic_pool::{SyncPool, SyncDropGuard};
1518 ///
1519 /// fn main() {
1520 /// let mut pool = SyncPool::new();
1521 ///
1522 /// let buffer: SyncDropGuard<Vec<u8>> = match pool.get_with_guard::<Vec<u8>>() {
1523 /// Some(mut buffer) => {
1524 /// // DropGuard is a smart pointer, so we can call Vec.clear() directly.
1525 /// buffer.clear();
1526 /// buffer
1527 /// }
1528 /// None => SyncDropGuard::new(Vec::new(), &pool),
1529 /// };
1530 ///
1531 /// assert_eq!(buffer.len(), 0);
1532 ///
1533 /// assert!(pool.get::<Vec<u8>>().is_none());
1534 ///
1535 /// // Will put the buffer back into the pool.
1536 /// drop(buffer);
1537 ///
1538 /// assert!(pool.get::<Vec<u8>>().is_some());
1539 /// }
1540 /// ```
1541 pub fn get_with_guard<T: Any + Send + Sync>(&mut self) -> Option<SyncDropGuard<T>> {
1542 match self.get::<T>() {
1543 Some(obj) => Some(SyncDropGuard::new(obj, self)),
1544 None => None,
1545 }
1546 }
1547
1548 /// Retrieve an object of the specified type with a drop guard. If there is no object of this type currently
1549 /// stored in the pool it will create one using its [`Default`] implementation.
1550 ///
1551 /// Once the returned [`SyncDropGuard`] goes out of scope it will automatically put
1552 /// the contained object pack into the pool. Note that the object might still get dropped
1553 /// by the pool if the corresponding internal buffer is full.
1554 ///
1555 /// # Example
1556 ///
1557 /// ```rust
1558 /// use generic_pool::{SyncPool, SyncDropGuard};
1559 ///
1560 /// fn main() {
1561 /// let mut pool = SyncPool::new();
1562 ///
1563 /// let buffer: SyncDropGuard<Vec<u8>> = pool.get_or_default_with_guard::<Vec<u8>>();
1564 ///
1565 /// assert_eq!(buffer.len(), 0);
1566 ///
1567 /// assert!(pool.get::<Vec<u8>>().is_none());
1568 ///
1569 /// // Will put the buffer back into the pool.
1570 /// drop(buffer);
1571 ///
1572 /// assert!(pool.get::<Vec<u8>>().is_some());
1573 /// }
1574 /// ```
1575 pub fn get_or_default_with_guard<T: Any + Send + Sync + Default>(&mut self) -> SyncDropGuard<T> {
1576 let obj = self.get_or_default::<T>();
1577
1578 SyncDropGuard::new(obj, self)
1579 }
1580
1581 /// Add an object to the pool. Unless the corresponding internal buffer is full, you can retrieve
1582 /// it later on by calling [`SyncPool.get()`](#method.get) or one of its variants.
1583 ///
1584 /// # Example
1585 ///
1586 /// ```rust
1587 /// use generic_pool::SyncPool;
1588 ///
1589 /// fn main() {
1590 /// let mut pool = SyncPool::new();
1591 ///
1592 /// assert!(pool.get::<Vec<u8>>().is_none());
1593 ///
1594 /// pool.put(vec![0u8; 1024]);
1595 ///
1596 /// let buffer = pool.get::<Vec<u8>>().unwrap();
1597 ///
1598 /// assert_eq!(buffer.len(), 1024);
1599 /// }
1600 /// ```
1601 pub fn put<T: Any + Send + Sync>(&self, obj: T) {
1602 let obj = Box::new(obj);
1603 let mut inner = self.inner.write().unwrap();
1604 inner.put::<T>(obj);
1605 }
1606}