pub struct Heap<const N: usize> { /* private fields */ }Expand description
The interface to a heap. This data structure is stored outside the heap somewhere, typically in a static variable, because every single byte of our heap is potentially available for allocation.
The generic parameter N specifies the number of steps to divide the available heap size by two. This will be the minimum allocable block size.
§Usage
// This can be a block of free system memory on your microcontroller.
const HEAP_MEM: usize = 0xFFF0_0000;
const HEAP_SIZE: usize = 0x0008_0000;
let mut heap: Heap<16> = unsafe {
Heap::new(NonNull::new(HEAP_MEM as *mut u8).unwrap(), HEAP_SIZE).unwrap()
};
let mem = heap.allocate(Layout::from_size_align(16, 16).unwrap()).unwrap();
// Yay! We have a 16-byte block of memory from the heap.§Usage (static initialization)
const HEAP_MEM: usize = 0xFFF0_0000;
const HEAP_SIZE: usize = 0x0008_0000;
// You'll want to wrap this heap in a lock abstraction for real-world use.
static mut ALLOCATOR: Heap<16> = unsafe {
Heap::new_unchecked(HEAP_MEM as *mut u8, HEAP_SIZE)
};
pub fn some_func() {
let mem = unsafe {
ALLOCATOR.allocate(Layout::from_size_align(16, 16).unwrap()).unwrap()
};
// Yay! We now have a 16-byte block from the heap without initializing it!
}Implementations§
Source§impl<const N: usize> Heap<N>
impl<const N: usize> Heap<N>
Sourcepub unsafe fn new(
heap_base: NonNull<u8>,
heap_size: usize,
) -> Result<Self, HeapError>
pub unsafe fn new( heap_base: NonNull<u8>, heap_size: usize, ) -> Result<Self, HeapError>
Create a new heap. If any parameter is invalid, this will return a HeapError.
Examples found in repository?
35fn main() {
36 // Allocate the backing memory for our heap. This memory _MUST_
37 // be aligned by at least 4096.
38 let layout = Layout::from_size_align(16384, 4096).unwrap();
39 let mem = unsafe { std::alloc::alloc(layout) };
40
41 // Construct our locked heap, with a minimum block size of 16 (16384 >> 10).
42 let heap: LockedHeap<10> = LockedHeap(Mutex::new(
43 unsafe { Heap::new(NonNull::new(mem).unwrap(), 16384) }.unwrap(),
44 ));
45 let mut vec = Vec::with_capacity_in(16, &heap);
46
47 vec.push(0usize);
48 vec.push(1usize);
49 vec.push(2usize);
50 vec.push(3usize);
51
52 println!("{:?}", vec);
53
54 // Drop the heap and vector before freeing the backing memory.
55 drop(vec);
56 drop(heap);
57
58 unsafe {
59 std::alloc::dealloc(mem, layout);
60 }
61}Sourcepub const unsafe fn new_unchecked(heap_base: *mut u8, heap_size: usize) -> Self
pub const unsafe fn new_unchecked(heap_base: *mut u8, heap_size: usize) -> Self
Create a new heap without checking for parameter validity. Useful for const heap creation.
§Safety
heap_base must be aligned on a
MIN_HEAP_ALIGN boundary, heap_size must be a power of 2, and
heap_size / 2.pow(free_lists.len()-1) must be greater than or
equal to size_of::<FreeBlock>(). Passing in invalid parameters
may do horrible things.
Sourcepub fn allocate(&mut self, layout: Layout) -> Result<*mut u8, AllocationError>
pub fn allocate(&mut self, layout: Layout) -> Result<*mut u8, AllocationError>
Allocate a block of memory large enough to contain layout,
and aligned to layout. This will return an AllocationError
if the alignment is greater than MIN_HEAP_ALIGN, or if
we can’t find enough memory.
All allocated memory must be passed to deallocate with the same
layout parameter, or else horrible things will happen.