Description
Currently this use case is supported for the Alloc
trait, but not GlobalAlloc
.
As discussed in #18 generic methods (I.e{alloc,dealloc}_one
) cannot be used to support this use case in GlobalAlloc
and maybe removed from Alloc
. An alternative that is consistent across both methods is needed.
Type information is necessary for ECS allocators, typed Pool/Slab allocators, many GC, STM optimizations, and describable for heap profilers, and exotic heuristic guided allocators as a significant source of free information.
-
Today there are many slab and generational indexed allocators. They are incompatible with box, std, and each other. They all provide some version of the following: allocation and deallocation of
T: Sized
, indexing/dereferencing and usually iterating overT
s.
By passing unsized allocations to an underlying or global allocator. They could easily implement the Alloc trait to take advantage of standard collections and boxes, but to do this they require knowing more than justLayout
, they requireTypeId
. -
I am working on a allocator for use a with both
Alloc
andGlobalAlloc
that requires typed pools ofSized
T
to support pause free optional GC. Without a method of differentiating allocations and deallocations that share the sameLayout
, but different types my use case is impossible.
In order to support all the mentioned use cases TypeId
needs to always be provided to allocations and deallocations of Sized
Types and N
Sized
Types . Layout looks like the best place to ensure TypeId
is always passed.
Layout
would have type_id_
added and TypeId
implementation would be changed to NonZeroU64
. type_id_
would not be considered by Eq
, so as not to break compatibility.
pub struct Layout {
size_: usize,
align_: NonZeroUsize,
type_id_: Option<TypeId>
}
Drawbacks
Adding another field to Layout could have a tiny performance cost.
alternatives
Originally I had wanted a separate set of functions for this use case analogous to Alloc::{alloc,dealloc}_array
and Alloc::{alloc,dealloc}_one
(like below), but this allows for human error (E.g calling the normal unsized set of functions when you have a sized type).
alloc_typed(&mut self, layout: Layout, _: TypeId) -> Result<NonNull<u8>, AllocErr> {
alloc(self, layout)
}