Struct mnemos_alloc::node::ActiveArr
source · #[repr(C)]pub(crate) struct ActiveArr<T> {
heap: *const AHeap,
capacity: usize,
data: [T; 0],
}
Expand description
An Active Array node type
This type represents a live allocation of a dynamic number of items,
similar to a Box<[T]>
in liballoc. Note that this is NOT the same as
a Vec<T>
, which can be dynamically resized. The underlying storage
here is always a fixed size, however that fixed size is chosen at
runtime, rather than at compile time.
It contains a pointer to the allocator, as well as storage for the items.
The contained data MUST be valid for the lifetime of the ActiveArr<T>
.
The ActiveArr type itself actually contains storage for zero T
items, however
it uses a [T; 0]
to force the correct alignment of the data
field. This
allows us to add size_of::<T>() * N
bytes directly following the item, which
can be indexed starting at the address of the data
field. This is done by
over-allocating space, and using the ActiveArr::data
function to obtain
access to the array storage.
NOTE: Although the data
field is not public (even within the crate),
EXTREME CARE must be taken NOT to access the data field through a reference
to an ActiveArr type. Creating a reference (rather than a pointer) to the
ActiveArr type itself serves as a “narrowing” of the provenance, which means
that accessing out of bound elements of data
(which is ALL of them, as
data “officially” has an array length of zero) is undefined behavior.
The ActiveArr::data
function handles this by using the addr_of!
macro
to obtain the pointer of the underlying array storage, WITHOUT narrowing
the provenance of the outer “supersized” allocation.
Fields§
§heap: *const AHeap
§capacity: usize
§data: [T; 0]
Implementations§
source§impl<T> ActiveArr<T>
impl<T> ActiveArr<T>
sourcepub(crate) unsafe fn layout_for_arr(ct: usize) -> Layout
pub(crate) unsafe fn layout_for_arr(ct: usize) -> Layout
Obtain a valid layout for an ActiveArr
As we can’t directly create a Layout
type for our Node<T>
/ActiveArr<T>
because of the !Sized
nature of [T]
, we instead do manual layout
surgery here instead. This function takes the alignment necessary for
a Node<T>
, but also increases the size to accomodate a [T]
with
a size of the given ct
parameter.
The given layout will always have a size >= the size of a Node<T>
, even
if the ActiveArr<T> + [T]
would be smaller than a Node<T>
.
sourcepub(crate) unsafe fn write_heap(this: NonNull<ActiveArr<T>>, heap: *const AHeap)
pub(crate) unsafe fn write_heap(this: NonNull<ActiveArr<T>>, heap: *const AHeap)
Set the heap pointer contained within the given ActiveArr<T>
.
This should ONLY be used to initialize the ActiveArr<T>
at time of allocation.
pub(crate) unsafe fn write_capacity( this: NonNull<ActiveArr<T>>, capacity: usize )
sourcepub(crate) unsafe fn data(this: NonNull<ActiveArr<T>>) -> (NonNull<T>, usize)
pub(crate) unsafe fn data(this: NonNull<ActiveArr<T>>) -> (NonNull<T>, usize)
Obtain a pointer to the start of the array storage, as well as the length of the array
NOTE: This VERY CAREFULLY avoids issues of provenance due to accessing “out of bounds”
of the data
field of the ActiveArr
type. See the docs of the ActiveArr type for
a more detailed discussion of these particularities.