hato
Heterogeneous Arenas of Trait Objects.
The collection is tied to a user trait, and elements are retrieved as trait objects.
This is an alternative to Vec<Box<dyn Trait>>, without requiring one allocation per entry.
A bump allocator like bumpalo will bring
similar benefits, but will not offer methods for memory reclamation.
This can be limiting for workloads involving alternating insertions and deletions.
Elements must implement the [Unscrupulous][unscrupulous::Unscrupulous] trait,
which makes cloning the arena fast, just a couple of memcpy calls per type of objects
stored in the collection. Be aware that this is quite constraining; make sure your types
fulfill the [requirements for the trait][unscrupulous::Unscrupulous].
Typical usage looks like this:
/// Arena will dole out elements as trait objects with this interface.
// Let's have some types implement our trait
// Declare types for are arena, and the corresponding handles
hato!;
As with to bump allocators, [Drop] implementations will not be invoked on deallocation
or calls to remove. If you need to run the logic contained in destructors,
you can acquire a mutable reference with get_mut, and then call [core::ptr::drop_in_place].
The macro offers some configuration options via named parameters:
- vis: visibility of the declared types; private by default
- mod: name of the module used to declare the types; defaults to "_hato_mod"
- wide_handles: indexes have a size of 8 bytes by default, this option raises this to 16 bytes
Types produced by this macro are subject to the ABA problem. Using handles of previously removed elements will not trigger errors but will return stale or newly inserted elements. This can lead to unexpected behavior, as shown below:
// Insert an element...
let x = arena.push;
// ... then remove it
arena.remove;
// ! We can still use the handle to access it
assert_eq!;
// Insert a new element into the arena
let _y = arena.push;
// ! The old handle accesses the repurposed capacity
assert_eq!;