//! Configurable policies for element reuse.
/// A policy defining how pooled elements of type `T` are reused.
///
/// A recycling policy provides two operations: [`Recycle::new_element`], which
/// defines how new elements of type `T` are *initially* constructed, and
/// [`Recycle::recycle`], which, given an `&mut T`, prepares that element for
/// reuse.
///
/// This trait is intended to allow defining custom policies to reuse values
/// that are expensive to create or destroy. If a type `T` owns a large memory
/// allocation or other reuseable resource (such as a file descriptor, network
/// connection, worker thread, et cetera), the [`recycle`](Self::recycle)
/// operation can clear any *data* associated with a particular use of that
/// value while retaining its memory allocation or other resources. For example,
/// the [`WithCapacity`] recycling policy clears standard library collections
/// such as `String` and `Vec` in place, retaining their allocated heap
/// capacity, so that future uses of those collections do not need to
/// reallocate.
/// A [`Recycle`] implementation for any type implementing [`Default`] and
/// [`Clone`].
///
/// This [creates new elements] by calling using [`Default::default()`].
/// Existing elements are [recycled] by calling [`Clone::clone_from`] with the
/// default value.
///
/// # Allocation Reuse
///
/// [`Clone::clone_from`] is not *guaranteed* to reuse existing
/// allocations in place. For a number of common types in the standard library,
/// such as [`Box`], [`String`], [`Vec`], and collections based on [`Vec`] (such
/// as [`VecDeque`] and [`BinaryHeap`]), `clone_from` is overridden to reuse
/// existing allocations in place. However, other types may not override
/// `clone_from` in this way.
///
/// `DefaultRecycle` will always *work* for types that implement [`Default`] and
/// [`Clone`], but it cannot be guaranteed to always reuse allocations. For a
/// more restrictive [`Recycle`] implementation that _will_ always reuse
/// existing allocations, consider [`WithCapacity`].
///
/// [creates new elements]: DefaultRecycle::new_element
/// [recycled]: DefaultRecycle::recycle
);
/// 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};
/// # use std::marker::PhantomData;
///
/// /// Some kind of exciting new heap-allocated collection.
/// pub struct MyCollection<T> {
/// // ...
/// # _p: PhantomData<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 {
/// // ...
/// # unimplemented!()
/// }
///
/// /// Returns the current allocated capacity of this `MyCollection`.
/// pub fn capacity(&self) -> usize {
/// // ...
/// # unimplemented!()
/// }
///
/// /// 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 {
/// // ...
/// # unimplemented!()
/// }
/// }
///
/// /// 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) {
/// // ...
/// # unimplemented!()
/// }
///
/// // 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.
///
/// [recycle]: Recycle::recycle
/// [`max_capacity`]: Self::max_capacity
/// [`min_capacity`]: Self::min_capacity
/// [`with_max_capacity`]: Self::with_max_capacity
/// [`with_min_capacity`]: Self::with_min_capacity
// TODO(eliza): consider making this public?
// TODO(eliza): consider making this a trait method with a default impl?
pub
// === impl WithCapacity ===
feature!
feature!