Expand description
A pointer type for bump allocation.
Box<'a, T> provides the simplest form of
bump allocation in bumpalo. Boxes provide ownership for this allocation, and
drop their contents when they go out of scope.
§Examples
Move a value from the stack to the heap by creating a Box:
use bumpalo::{Bump, boxed::Box};
let b = Bump::new();
let val: u8 = 5;
let boxed: Box<u8> = Box::new_in(val, &b);Move a value from a Box back to the stack by dereferencing:
use bumpalo::{Bump, boxed::Box};
let b = Bump::new();
let boxed: Box<u8> = Box::new_in(5, &b);
let val: u8 = *boxed;Running Drop implementations on bump-allocated values:
use bumpalo::{Bump, boxed::Box};
use std::sync::atomic::{AtomicUsize, Ordering};
static NUM_DROPPED: AtomicUsize = AtomicUsize::new(0);
struct CountDrops;
impl Drop for CountDrops {
fn drop(&mut self) {
NUM_DROPPED.fetch_add(1, Ordering::SeqCst);
}
}
// Create a new bump arena.
let bump = Bump::new();
// Create a `CountDrops` inside the bump arena.
let mut c = Box::new_in(CountDrops, &bump);
// No `CountDrops` have been dropped yet.
assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 0);
// Drop our `Box<CountDrops>`.
drop(c);
// Its `Drop` implementation was run, and so `NUM_DROPS` has been incremented.
assert_eq!(NUM_DROPPED.load(Ordering::SeqCst), 1);Creating a recursive data structure:
use bumpalo::{Bump, boxed::Box};
let b = Bump::new();
#[derive(Debug)]
enum List<'a, T> {
Cons(T, Box<'a, List<'a, T>>),
Nil,
}
let list: List<i32> = List::Cons(1, Box::new_in(List::Cons(2, Box::new_in(List::Nil, &b)), &b));
println!("{:?}", list);This will print Cons(1, Cons(2, Nil)).
Recursive structures must be boxed, because if the definition of Cons
looked like this:
Cons(T, List<T>),It wouldn’t work. This is because the size of a List depends on how many
elements are in the list, and so we don’t know how much memory to allocate
for a Cons. By introducing a Box<'a, T>, which has a defined size, we know how
big Cons needs to be.
§Memory layout
For non-zero-sized values, a Box will use the provided Bump allocator for
its allocation. It is valid to convert both ways between a Box and a
pointer allocated with the Bump allocator, given that the
Layout used with the allocator is correct for the type. More precisely,
a value: *mut T that has been allocated with the Bump allocator
with Layout::for_value(&*value) may be converted into a box using
Box::<T>::from_raw(value). Conversely, the memory backing a value: *mut T obtained from Box::<T>::into_raw will be deallocated by the
Bump allocator with Layout::for_value(&*value).
Note that roundtrip Box::from_raw(Box::into_raw(b)) looses the lifetime bound to the
Bump immutable borrow which guarantees that the allocator will not be reset
and memory will not be freed.
Structs§
- Box
- An owned pointer to a bump-allocated
Tvalue, that runsDropimplementations.