Struct thingbuf::recycling::WithCapacity
source · pub struct WithCapacity { /* private fields */ }
Expand description
A Recycle
implementation for types that provide with_capacity
,
clear
, and shrink_to
methods.
This includes all array-based collections in the Rust standard library, such
as Vec
, String
, VecDeque
, and BinaryHeap
, as well as
HashMap
and HashSet
.
§Usage
By default, this type will always recycle elements by clearing all values in place, returning all allocated capacity. [New elements] are allocated with capacity for 0 values; they will allocate when first used.
§Implementations for Other Types
Recycle
implementations may be added for similar data structures
implemented in other libraries. The min_capacity
and
max_capacity
methods expose the configured initial capacity and upper
bound.
As an example, a library that implements an array-based data structure with
with_capacity
, clear
, and shrink_to
methods can implement Recycle
for WithCapacity
like so:
use thingbuf::recycling::{self, Recycle};
/// Some kind of exciting new heap-allocated collection.
pub struct MyCollection<T> {
// ...
}
impl<T> MyCollection<T> {
/// Returns a new `MyCollection` with enough capacity to hold
/// `capacity` elements without reallocationg.
pub fn with_capacity(capacity: usize) -> Self {
// ...
}
/// Returns the current allocated capacity of this `MyCollection`.
pub fn capacity(&self) -> usize {
// ...
}
/// Shrinks the capacity of the `MyCollection` with a lower bound.
///
/// The capacity will remain at least as large as both the length
/// and the supplied value.
///
/// If the current capacity is less than the lower limit, this is a no-op.
pub fn shrink_to(&mut self, min_capacity: usize) {
if self.capacity() > min_capacity {
// ...
}
}
/// Clears the `MyCollection`, removing all values.
///
/// This does not change the current allocated capacity. The
/// `MyCollection` will still have enough allocated storage to hold
/// at least the current number of values.
pub fn clear(&mut self) {
// ...
}
// Other cool and exciting methods go here!
}
// Because `MyCollection<T>` has `with_capacity`, `shrink_to`, and `clear` methods,
// we can implement `Recycle<MyCollection<T>>` for `WithCapacity` exactly the same
// way as it is implemented for standard library collections.
impl<T> Recycle<MyCollection<T>> for recycling::WithCapacity {
fn new_element(&self) -> MyCollection<T> {
// Allocate a new element with the minimum initial capacity:
MyCollection::with_capacity(self.min_capacity())
}
fn recycle(&self, element: &mut MyCollection<T>) {
// Recycle the element by clearing it in place, and then limiting the
// allocated capacity to the upper bound, if one is set:
element.clear();
element.shrink_to(self.max_capacity());
}
}
§Allocation Reuse
When an upper bound is not set, this recycling policy will always reuse any allocated capacity when recycling an element. Over time, the number of reallocations required to grow items in a pool should decrease, amortizing reallocations over the lifetime of the program.
Of course, this means that it is technically possible for the allocated
capacity of the pool to grow infinitely, which can cause a memory leak if
used incorrectly. Therefore, it is also possible to set an upper bound on
idle capacity, using with_max_capacity
. When such a bound is set,
recycled elements will be shrunk down to that capacity if they have grown
past the upper bound while in use. If this is the case, reallocations may
occur more often, but if the upper bound is higher than the typical required
capacity, they should remain infrequent.
If elements will not require allocations of differing sizes, and the size is
known in advance (e.g. a pool of HashMap
s that always have exactly 64
elements), the with_max_capacity
and with_min_capacity
methods can
be called with the same value. This way, elements will always be initially
allocated with exactly that much capacity, and will only be shrunk if they
ever exceed that capacity. If the elements never grow beyond the specified
capacity, this should mean that no additional allocations will ever occur
once the initial pool of elements are allocated.
Implementations§
source§impl WithCapacity
impl WithCapacity
sourcepub const fn new() -> Self
pub const fn new() -> Self
Returns a new WithCapacity
.
By default, the maximum capacity is unconstrained, and the minimum capacity is 0. Existing allocations will always be reused, regardless of size, and new elements will be created with 0 capacity.
To add an upper bound on re-used capacity, use
WithCapacity::with_max_capacity
. To allocate elements with an
initial capacity, use WithCapacity::with_min_capacity
.
sourcepub const fn with_max_capacity(self, max: usize) -> Self
pub const fn with_max_capacity(self, max: usize) -> Self
Sets an upper bound on the capacity that will be reused when recycling elements.
When an element is recycled, if its capacity exceeds the max value, it will be shrunk down to that capacity. This will result in a reallocation, but limits the total capacity allocated by the pool, preventing unbounded memory use.
Elements may still exceed the configured max capacity while they are in use; this value only configures what happens when they are returned to the pool.
§Examples
use thingbuf::recycling::{Recycle, WithCapacity};
// Create a recycler with max capacity of 8.
let recycle = WithCapacity::new().with_max_capacity(8);
// Create a new string using that recycler.
let mut s: String = recycle.new_element();
assert_eq!(s.capacity(), 0);
// Now, write some data to the string.
s.push_str("hello, world");
// The string's capacity must be at least the length of the
// string 'hello, world'.
assert!(s.capacity() >= "hello, world".len());
// After recycling the string, its capacity will be shrunk down
// to the configured max capacity.
recycle.recycle(&mut s);
assert_eq!(s.capacity(), 8);
sourcepub const fn with_min_capacity(self, min: usize) -> Self
pub const fn with_min_capacity(self, min: usize) -> Self
Sets the minimum capacity when allocating new elements.
When new elements are created, they will be allocated with at least
min
capacity.
Note that this is a lower bound. Elements may be allocated with
greater than the minimum capacity, depending on the behavior of the
element being allocated, but there will always be at least min
capacity.
§Examples
use thingbuf::recycling::{Recycle, WithCapacity};
// A recycler without a minimum capacity.
let no_min = WithCapacity::new();
// A new element created by this recycler will not
// allocate any capacity until it is used.
let s: String = no_min.new_element();
assert_eq!(s.capacity(), 0);
// Now, configure a minimum capacity.
let with_min = WithCapacity::new().with_min_capacity(8);
// New elements created by this recycler will always be allocated
// with at least the specified capacity.
let s: String = with_min.new_element();
assert!(s.capacity() >= 8);
sourcepub fn min_capacity(&self) -> usize
pub fn min_capacity(&self) -> usize
Returns the minimum initial capacity when allocating new elements.
This method can be used to implement Recycle<T> for WithCapacity
where
T
is a type defined outside of this crate. See the WithCapacity
documentation for details.
§Examples
use thingbuf::recycling::{Recycle, WithCapacity};
let recycle = WithCapacity::new();
assert_eq!(recycle.min_capacity(), 0);
use thingbuf::recycling::{Recycle, WithCapacity};
let recycle = WithCapacity::new().with_min_capacity(64);
assert_eq!(recycle.min_capacity(), 64);
sourcepub fn max_capacity(&self) -> usize
pub fn max_capacity(&self) -> usize
Returns the maximum retained capacity when recycling elements.
If no upper bound is configured, this will return usize::MAX
.
This method can be used to implement Recycle<T> for WithCapacity
where
T
is a type defined outside of this crate. See the WithCapacity
documentation for details.
§Examples
use thingbuf::recycling::{Recycle, WithCapacity};
let recycle = WithCapacity::new();
assert_eq!(recycle.max_capacity(), usize::MAX);
use thingbuf::recycling::{Recycle, WithCapacity};
let recycle = WithCapacity::new().with_max_capacity(64);
assert_eq!(recycle.max_capacity(), 64);
Trait Implementations§
source§impl Clone for WithCapacity
impl Clone for WithCapacity
source§fn clone(&self) -> WithCapacity
fn clone(&self) -> WithCapacity
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moresource§impl Debug for WithCapacity
impl Debug for WithCapacity
source§impl Default for WithCapacity
impl Default for WithCapacity
source§impl<T: Ord> Recycle<BinaryHeap<T>> for WithCapacity
Available on crate feature alloc
only.
impl<T: Ord> Recycle<BinaryHeap<T>> for WithCapacity
alloc
only.source§fn new_element(&self) -> BinaryHeap<T>
fn new_element(&self) -> BinaryHeap<T>
T
. Read moresource§fn recycle(&self, element: &mut BinaryHeap<T>)
fn recycle(&self, element: &mut BinaryHeap<T>)
element
element for reuse. Read moresource§impl<K, V, S> Recycle<HashMap<K, V, S>> for WithCapacity
Available on crate feature std
only.
impl<K, V, S> Recycle<HashMap<K, V, S>> for WithCapacity
std
only.source§impl<K, S> Recycle<HashSet<K, S>> for WithCapacity
Available on crate feature std
only.
impl<K, S> Recycle<HashSet<K, S>> for WithCapacity
std
only.source§impl Recycle<String> for WithCapacity
Available on crate feature alloc
only.
impl Recycle<String> for WithCapacity
alloc
only.source§impl<T> Recycle<Vec<T>> for WithCapacity
Available on crate feature alloc
only.
impl<T> Recycle<Vec<T>> for WithCapacity
alloc
only.