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

customizable release policies #30

Closed
hawkw opened this issue Jan 16, 2022 · 0 comments · Fixed by #33
Closed

customizable release policies #30

hawkw opened this issue Jan 16, 2022 · 0 comments · Fixed by #33

Comments

@hawkw
Copy link
Owner

hawkw commented Jan 16, 2022

it could be nice to have some kind of trait to customize how elements are released before being reused (and how new empty elements are generated). this would kind of obviate the need for the separate StringBuf type.

@hawkw hawkw closed this as completed in #33 Feb 28, 2022
hawkw added a commit that referenced this issue 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 `String`s, where the `String` is cleared in place
prior to writing to, but this only works for `String`s. `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 `String`s 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]>
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 a pull request may close this issue.

1 participant