Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(recycling): add customizable recycling policies #33

Merged
merged 11 commits into from
Feb 28, 2022
Merged

Conversation

hawkw
Copy link
Owner

@hawkw hawkw commented Feb 28, 2022

Motivation

Currently, all queues and channels in thingbuf require that items in
the queue/channel implement Default, because Default is used to fill
slots when they are initially allocated. Furthermore, when slots are
checked out for writing to, they are not cleared prior to being written
to --- the user code is responsible for clearing them if needed.

The StringBuf type currently implements special behavior
specifically for Strings, where the String is cleared in place
prior to writing to, but this only works for Strings. StringBuf also
provides an API for limiting the maximum capacity of "empty" strings, so
that they can be shrunk down to that capacity when returning them to the
pool. This allows introducing an upper bound on the capacity allocated
by unused strings. However, again, this only works with Strings and is
only provided by the StringBuf type.

This isn't ideal --- users shouldn't have to be responsible for
clearing non-String types when reusing allocations.

Solution

This branch introduces a new Recycle<T> trait that defines a policy
for how T-typed pooled objects should be reused. Recycle<T> defines
two methods:

  • fn new_element(&self) -> T creates a new element
  • fn recycle(&self, element: &mut T) clears a pooled element for reuse

This allows a Recycle implementation to define the lifecycle of a
pooled item.

In addition, we define a couple of pre-made Recycle implementations:

  • DefaultRecycle, which implements Recycle for all types T where
    T: Default + Clone. This is used by all thingbuf types by default.
    It creates new elements using Default::default, and recycles them
    using element.clone_from(T::default()).

    Clone::clone_from is not guaranteed to re-use existing capacity,
    but it's overridden by most array-based collections (such as the ones
    in the standard library) to do so --- it should be equivalent to
    .clear() when cloning from an empty collection. However, this policy
    will still work with types that don't have a clear-in-place
    function.

  • WithCapacity implements Recycle only for types that define
    with_capacity, shrink_to, and clear methods, like all
    array-based collections in the Rust standard library. Unlike
    DefaultRecycle, it is guaranteed to clear elements in place and
    retain any previously allocated capacity.

    It can also be configured to add both upper and lower bounds on
    capacity. When there is a lower bound, new elements are allocated with
    that value as their initial capacity, rather than being allocated with
    0 capacity. When an upper bound is set, it will call shrink_to prior
    to clearing elements, to limit the total allocated capacity retained
    by the pool.

    WithCapacity currently implements Recycle for all alloc and
    std types that define the requisite methods: Vec, String,
    VecDeque, and BinaryHeap when the alloc feature is enabled, and
    HashMap and HashSet as well, when the std feature is enabled.

Finally, I've modified the existing queue and channel types to allow
configuring them to use a Recycle implementation. The StringBuf type
is removed, as it's now obviated by the new APIs.

Future Work

We may wish to factor out the recycling module into its own crate, so
that it can be used in other libraries.

Closes #30

Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
@hawkw hawkw self-assigned this Feb 28, 2022
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
Signed-off-by: Eliza Weisman <[email protected]>
@hawkw hawkw merged commit 54e5353 into main Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

customizable release policies
1 participant