pub unsafe trait Allocator {
// Required methods
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
// Provided methods
fn allocate_zeroed(
&self,
layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> { ... }
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> { ... }
unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> { ... }
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> { ... }
fn by_ref(&self) -> &Self
where Self: Sized { ... }
}
Expand description
An implementation of Allocator can allocate, grow, shrink, and deallocate
arbitrary blocks of data described via Layout
.
Allocator is designed to be implemented on ZSTs, references, or smart
pointers because having an allocator like MyAlloc([u8; N])
cannot be
moved, without updating the pointers to the allocated memory.
Unlike GlobalAlloc
, zero-sized allocations are allowed in Allocator
.
If an underlying allocator does not support this (like jemalloc
) or
return a null pointer (such as libc::malloc
), this must be caught by
the implementation.
§Currently allocated memory
Some of the methods require that a memory block be currently allocated via an allocator. This means that:
- The starting address for that memory block was previously returned by
allocate
,grow
, orshrink
, and - The memory block has not been subsequently deallocated, where blocks are
either deallocated directly by being passed to deallocate or were change
by being passed to
grow
orshrink
that returnsOk
. Ifgrow
orshrink
have returnedErr
, the passed pointer remains valid.
§Memory fitting
Some of the methods require that a layout fit a memory block. What it means for a layout to “fit” a memory block means (or equivalently, for a memory block to “fit” a layout) is that the following conditions must hold:
- The block must be allocated with the same alignment as
layout.align()
, and - The provided
layout.size()
must fall in the rangemin..=max
, where:min
is the size of the layout most recently used to allocate the block, andmax
is the latest actual size returned fromallocate
,grow
, orshrink
.
#Safety
- Memory blocks returned from an allocator must point to valid memory and retain their validity until the instance and all of its clones are dropped,
- Cloning or moving the allocator must not invalidate memory blocks returned from this allocator. A cloned allocator must behave like the same allocator, and
- Any pointer to a memory block which is currently allocated may be passed to any other method of the allocator.
Required Methods§
Sourcefn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
Try to allocate a slice of memory within this allocator instance, returning the new allocation.
Sourceunsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)
Release an allocation produced by this allocator.
§Safety
The value ptr
must represent an allocation produced by this allocator, otherwise
a memory access error may occur. The value old_layout
must correspond to the
layout produced by the previous allocation.
Provided Methods§
Sourcefn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
Try to allocate a slice of memory within this allocator instance, returning the new allocation. The memory will be initialized with zeroes.
Sourceunsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Try to extend the size of an allocation to accomodate a new, larger layout.
Sourceunsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow_zeroed( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Try to extend the size of an allocation to accomodate a new, larger layout. Fill the extra capacity with zeros.