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 { ... }
}
allocator_api
)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.
An allocator for MyAlloc([u8; N])
cannot be moved, without updating the pointers to the
allocated memory.
In contrast to GlobalAlloc
, Allocator
allows zero-sized allocations. If an underlying
allocator does not support this (like jemalloc) or responds by returning 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 is currently allocated by 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 subsequently been deallocated.
A memory block is deallocated by a call to deallocate
,
or by a call to grow
or shrink
that returns Ok
.
A call to grow
or shrink
that returns Err
,
does not deallocate the memory block passed to it.
§Memory fitting
Some of the methods require that a layout
fit a memory block or vice versa. This means that the
following conditions must hold:
- the memory block must be currently allocated with alignment of
layout.align()
, and layout.size()
must fall in the rangemin ..= max
, where:
§Safety
Memory blocks that are currently allocated by an allocator, must point to valid memory, and retain their validity while until either:
- the memory block is deallocated, or
- the allocator is dropped.
Copying, cloning, or moving the allocator must not invalidate memory blocks returned from it. A copied or cloned allocator must behave like the original allocator.
A memory block which is currently allocated may be passed to any method of the allocator that accepts such an argument.
Required Methods§
Sourcefn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
)
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocator_api
)Attempts to allocate a block of memory.
On success, returns a NonNull<[u8]>
meeting the size and alignment guarantees of layout
.
The returned block may have a larger size than specified by layout.size()
, and may or may
not have its contents initialized.
The returned block of memory remains valid as long as it is [currently allocated] and the shorter of:
- the borrow-checker lifetime of the allocator type itself.
- as long as at the allocator and all its clones has not been dropped.
§Errors
Returning Err
indicates that either memory is exhausted or layout
does not meet
allocator’s size or alignment constraints.
Implementations are encouraged to return Err
on memory exhaustion rather than panicking or
aborting, but this is not a strict requirement. (Specifically: it is legal to implement
this trait atop an underlying native allocation library that aborts on memory exhaustion.)
Clients wishing to abort computation in response to an allocation error are encouraged to
call the handle_alloc_error
function, rather than directly invoking panic!
or similar.
Sourceunsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)
🔬This is a nightly-only experimental API. (allocator_api
)
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout)
allocator_api
)Deallocates the memory referenced by ptr
.
§Safety
ptr
must denote a block of memory currently allocated via this allocator, andlayout
must fit that block of memory.
Provided Methods§
Sourcefn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
)
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocator_api
)Behaves like allocate
, but also ensures that the returned memory is zero-initialized.
§Errors
Returning Err
indicates that either memory is exhausted or layout
does not meet
allocator’s size or alignment constraints.
Implementations are encouraged to return Err
on memory exhaustion rather than panicking or
aborting, but this is not a strict requirement. (Specifically: it is legal to implement
this trait atop an underlying native allocation library that aborts on memory exhaustion.)
Clients wishing to abort computation in response to an allocation error are encouraged to
call the handle_alloc_error
function, rather than directly invoking panic!
or similar.
Sourceunsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
)
unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
allocator_api
)Attempts to extend the memory block.
Returns a new NonNull<[u8]>
containing a pointer and the actual size of the allocated
memory. The pointer is suitable for holding data described by new_layout
. To accomplish
this, the allocator may extend the allocation referenced by ptr
to fit the new layout.
If this returns Ok
, then ownership of the memory block referenced by ptr
has been
transferred to this allocator. Any access to the old ptr
is Undefined Behavior, even if the
allocation was grown in-place. The newly returned pointer is the only valid pointer
for accessing this memory now.
If this method returns Err
, then ownership of the memory block has not been transferred to
this allocator, and the contents of the memory block are unaltered.
§Safety
ptr
must denote a block of memory currently allocated via this allocator.old_layout
must fit that block of memory (Thenew_layout
argument need not fit it.).new_layout.size()
must be greater than or equal toold_layout.size()
.
Note that new_layout.align()
need not be the same as old_layout.align()
.
§Errors
Returns Err
if the new layout does not meet the allocator’s size and alignment
constraints of the allocator, or if growing otherwise fails.
Implementations are encouraged to return Err
on memory exhaustion rather than panicking or
aborting, but this is not a strict requirement. (Specifically: it is legal to implement
this trait atop an underlying native allocation library that aborts on memory exhaustion.)
Clients wishing to abort computation in response to an allocation error are encouraged to
call the handle_alloc_error
function, rather than directly invoking panic!
or similar.
Sourceunsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
)
unsafe fn grow_zeroed( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
allocator_api
)Behaves like grow
, but also ensures that the new contents are set to zero before being
returned.
The memory block will contain the following contents after a successful call to
grow_zeroed
:
- Bytes
0..old_layout.size()
are preserved from the original allocation. - Bytes
old_layout.size()..old_size
will either be preserved or zeroed, depending on the allocator implementation.old_size
refers to the size of the memory block prior to thegrow_zeroed
call, which may be larger than the size that was originally requested when it was allocated. - Bytes
old_size..new_size
are zeroed.new_size
refers to the size of the memory block returned by thegrow_zeroed
call.
§Safety
ptr
must denote a block of memory currently allocated via this allocator.old_layout
must fit that block of memory (Thenew_layout
argument need not fit it.).new_layout.size()
must be greater than or equal toold_layout.size()
.
Note that new_layout.align()
need not be the same as old_layout.align()
.
§Errors
Returns Err
if the new layout does not meet the allocator’s size and alignment
constraints of the allocator, or if growing otherwise fails.
Implementations are encouraged to return Err
on memory exhaustion rather than panicking or
aborting, but this is not a strict requirement. (Specifically: it is legal to implement
this trait atop an underlying native allocation library that aborts on memory exhaustion.)
Clients wishing to abort computation in response to an allocation error are encouraged to
call the handle_alloc_error
function, rather than directly invoking panic!
or similar.
Sourceunsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
🔬This is a nightly-only experimental API. (allocator_api
)
unsafe fn shrink( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
allocator_api
)Attempts to shrink the memory block.
Returns a new NonNull<[u8]>
containing a pointer and the actual size of the allocated
memory. The pointer is suitable for holding data described by new_layout
. To accomplish
this, the allocator may shrink the allocation referenced by ptr
to fit the new layout.
If this returns Ok
, then ownership of the memory block referenced by ptr
has been
transferred to this allocator. Any access to the old ptr
is Undefined Behavior, even if the
allocation was shrunk in-place. The newly returned pointer is the only valid pointer
for accessing this memory now.
If this method returns Err
, then ownership of the memory block has not been transferred to
this allocator, and the contents of the memory block are unaltered.
§Safety
ptr
must denote a block of memory currently allocated via this allocator.old_layout
must fit that block of memory (Thenew_layout
argument need not fit it.).new_layout.size()
must be smaller than or equal toold_layout.size()
.
Note that new_layout.align()
need not be the same as old_layout.align()
.
§Errors
Returns Err
if the new layout does not meet the allocator’s size and alignment
constraints of the allocator, or if shrinking otherwise fails.
Implementations are encouraged to return Err
on memory exhaustion rather than panicking or
aborting, but this is not a strict requirement. (Specifically: it is legal to implement
this trait atop an underlying native allocation library that aborts on memory exhaustion.)
Clients wishing to abort computation in response to an allocation error are encouraged to
call the handle_alloc_error
function, rather than directly invoking panic!
or similar.