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
- An owned pointer to a bump-allocated
T
value, that runsDrop
implementations.