generic_pool
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.
The main advantage of this library compared to other pools is that it can store and retrieve an abritrary number of different objects seemlessly. 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, 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 object type.
This library is 100% pure Rust, uses no unstable or nighly only features and, most importantly, does not contain any unsafe code. It also has zero dependencies on default, but has an optional serde feature which enables de-/serialization of the configuration by Serde.
Features
- Provides a lightweigth regular version as well as a thread-save sync version.
- Does optionally provide a drop guard which will automatically add objects back to the store after they go out of scope.
- Allows configuring the maximum number of stored objects to prevent RAM exhaustion.
- Allows configuring the rate at which the internal capacity gets increased over time.
- Each configuration option can be set for each object type individually.
- You can also set a fallback configuration for object types for which no constum configuration was set.
- Provides optional auto-creation of objects which implement the
Defaulttrait. - Offers cheap
Cloning, so you can easily use the same pool in many places.
A quick example
This example demonstrates the most basic usage. We define two different structs, Person and Animal.
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.
use Pool;
How it works
This library makes use of the Any trait which provides a globally unique TypeId for each object.
This TypeId gets used as the key in a HashMap where the values are Vec's of boxed trait objects implementing the Any trait.
Upon adding/getting an object from the pool the objects TypeId gets used to retrieve the correct Vec where the value gets pushed to or popped from.
When getting a value, we use Box.downcast() to convert the boxed trait object back to a boxed version of the concrete type. Afterwards we can simply move the concrete object out of the box by dereferencing it, see the accepted answer at this Stackoverflow question.
Security
The pool does not modify the objects it receives or gives out in any way, and does thus in particular not reset objects properly. It is your responsibility to reset objects as appropriate either before adding them back to the store, or after receiving them. Otherwise you will likely open up security holes by accidentaly using data from earlier operations.
A common bad example
Many frontend APIs do also provide priviledged access if they receive the proper credentials. Depending on the implementation the admin flag might only get explicitly set if some special credentials are send over. Without resetting the admin flag of recycled request objects this can open up a big security hole.
use Pool;
The solution
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 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.
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 from the pool.
use ;
/// A local trait providing the reset logic for all recycled objects.
// We implement the trait on any drop guard by this.
Configuration
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. These settings always apply to a specific type of object beeing stored in the pool, and never at the pool as a whole. That is if you store e.g. 2 different object types and configure a default 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.
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
fallback config for the pool, the pool will use the default values of the Config object.
Example
use ;
License
This library is licensed under the MIT license.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this library by you, shall be licensed as MIT, without any additional terms or conditions.