Open
Description
📢 This feature has a dedicated working group, please direct comments and concerns to the working group's repo.
The remainder of this post is no longer an accurate summary of the current state; see that dedicated working group instead.
Old content
Original Post:
FCP proposal: #32838 (comment)
FCP checkboxes: #32838 (comment)
Tracking issue for rust-lang/rfcs#1398 and the std::heap
module.
- land
struct Layout
,trait Allocator
, and default implementations inalloc
crate (Allocator integration #42313) - decide where parts should live (e.g. default impls has dependency on
alloc
crate, butLayout
/Allocator
could be inlibcore
...) (Allocator integration #42313) - fixme from source code: audit default implementations (in
Layout
for overflow errors, (potentially switching to overflowing_add and overflowing_mul as necessary). - decide if
realloc_in_place
should be replaced withgrow_in_place
andshrink_in_place
(comment) (Allocator integration #42313) - review arguments for/against associated error type (see subthread here)
- determine what the requirements are on the alignment provided to
fn dealloc
. (See discussion on allocator rfc and global allocator rfc and traitAlloc
PR.)- Is it required to deallocate with the exact
align
that you allocate with? Concerns have been raised that allocators like jemalloc don't require this, and it's difficult to envision an allocator that does require this. (more discussion). @ruuda and @rkruppe look like they've got the most thoughts so far on this.
- Is it required to deallocate with the exact
- should
AllocErr
beError
instead? (comment) - Is it required to deallocate with the exact size that you allocate with? With the
usable_size
business we may wish to allow, for example, that you if you allocate with(size, align)
you must deallocate with a size somewhere in the range ofsize...usable_size(size, align)
. It appears that jemalloc is totally ok with this (doesn't require you to deallocate with a precisesize
you allocate with) and this would also allowVec
to naturally take advantage of the excess capacity jemalloc gives it when it does an allocation. (although actually doing this is also somewhat orthogonal to this decision, we're just empoweringVec
). So far @gankro has most of the thoughts on this. (@alexcrichton believes this was settled in Allocator integration #42313 due to the definition of "fits") - similar to previous question: Is it required to deallocate with the exact alignment that you allocated with? (See comment from 5 June 2017)
- OSX/
alloc_system
is buggy on huge alignments (e.g. an align of1 << 32
) if huge requested align, alloc_system heap::allocate on OS X returns unaligned values #30170 Add precondition toLayout
that thealign
fit in a u32. #43217 - should
Layout
provide afn stride(&self)
method? (See also Separate size and stride for types rfcs#1397, Collapse trailing padding #17027 ) -
Allocator::owns
as a method? Alloc: Add owns method #44302
State of std::heap
after #42313:
pub struct Layout { /* ... */ }
impl Layout {
pub fn new<T>() -> Self;
pub fn for_value<T: ?Sized>(t: &T) -> Self;
pub fn array<T>(n: usize) -> Option<Self>;
pub fn from_size_align(size: usize, align: usize) -> Option<Layout>;
pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Layout;
pub fn size(&self) -> usize;
pub fn align(&self) -> usize;
pub fn align_to(&self, align: usize) -> Self;
pub fn padding_needed_for(&self, align: usize) -> usize;
pub fn repeat(&self, n: usize) -> Option<(Self, usize)>;
pub fn extend(&self, next: Self) -> Option<(Self, usize)>;
pub fn repeat_packed(&self, n: usize) -> Option<Self>;
pub fn extend_packed(&self, next: Self) -> Option<(Self, usize)>;
}
pub enum AllocErr {
Exhausted { request: Layout },
Unsupported { details: &'static str },
}
impl AllocErr {
pub fn invalid_input(details: &'static str) -> Self;
pub fn is_memory_exhausted(&self) -> bool;
pub fn is_request_unsupported(&self) -> bool;
pub fn description(&self) -> &str;
}
pub struct CannotReallocInPlace;
pub struct Excess(pub *mut u8, pub usize);
pub unsafe trait Alloc {
// required
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>;
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout);
// provided
fn oom(&mut self, _: AllocErr) -> !;
fn usable_size(&self, layout: &Layout) -> (usize, usize);
unsafe fn realloc(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<*mut u8, AllocErr>;
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr>;
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr>;
unsafe fn realloc_excess(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<Excess, AllocErr>;
unsafe fn grow_in_place(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<(), CannotReallocInPlace>;
unsafe fn shrink_in_place(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<(), CannotReallocInPlace>;
// convenience
fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
where Self: Sized;
unsafe fn dealloc_one<T>(&mut self, ptr: Unique<T>)
where Self: Sized;
fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
where Self: Sized;
unsafe fn realloc_array<T>(&mut self,
ptr: Unique<T>,
n_old: usize,
n_new: usize) -> Result<Unique<T>, AllocErr>
where Self: Sized;
unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Result<(), AllocErr>
where Self: Sized;
}
/// The global default allocator
pub struct Heap;
impl Alloc for Heap {
// ...
}
impl<'a> Alloc for &'a Heap {
// ...
}
/// The "system" allocator
pub struct System;
impl Alloc for System {
// ...
}
impl<'a> Alloc for &'a System {
// ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Metadata
Assignees
Labels
Area: Custom and system allocatorsBlocker: Approved by a merged RFC but not yet implemented.Blocker: Implemented in the nightly compiler and unstable.Category: A tracking issue for an RFC or an unstable feature.Libs issues that are tracked on the team's project board.Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation.Relevant to the language team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.