Module bumpalo::boxed [−][src]
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<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 lifetime bound to the
Bump
immutable borrow which guarantees that allocator will not be reset
and memory will not be freed.
Structs
Box | An owned pointer to a bump-allocated |