[][src]Struct bumpalo::Bump

pub struct Bump { /* fields omitted */ }

An arena to bump allocate into.

No Drops

Objects that are bump-allocated will never have their Drop implementation called — unless you do it manually yourself. This makes it relatively easy to leak memory or other resources.

If you have a type which internally manages

  • an allocation from the global heap (e.g. Vec<T>),
  • open file descriptors (e.g. std::fs::File), or
  • any other resource that must be cleaned up (e.g. an mmap)

and relies on its Drop implementation to clean up the internal resource, then if you allocate that type with a Bump, you need to find a new way to clean up after it yourself.

Potential solutions are

  • calling drop_in_place or using std::mem::ManuallyDrop to manually drop these types,
  • using bumpalo::collections::Vec instead of std::vec::Vec, or
  • simply avoiding allocating these problematic types within a Bump.

Note that not calling Drop is memory safe! Destructors are never guaranteed to run in Rust, you can't rely on them for enforcing memory safety.

Example

use bumpalo::Bump;

// Create a new bump arena.
let bump = Bump::new();

// Allocate values into the arena.
let forty_two = bump.alloc(42);
assert_eq!(*forty_two, 42);

// Mutable references are returned from allocation.
let mut s = bump.alloc("bumpalo");
*s = "the bump allocator; and also is a buffalo";

Methods

impl Bump[src]

pub fn new() -> Bump[src]

Construct a new arena to bump allocate into.

Example

let bump = bumpalo::Bump::new();

pub fn reset(&mut self)[src]

Reset this bump allocator.

Performs mass deallocation on everything allocated in this arena by resetting the pointer into the underlying chunk of memory to the start of the chunk. Does not run any Drop implementations on deallocated objects; see the Bump type's top-level documentation for details.

If this arena has allocated multiple chunks to bump allocate into, then the excess chunks are returned to the global allocator.

Example

let mut bump = bumpalo::Bump::new();

// Allocate a bunch of things.
{
    for i in 0..100 {
        bump.alloc(i);
    }
}

// Reset the arena.
bump.reset();

// Allocate some new things in the space previously occupied by the
// original things.
for j in 200..400 {
    bump.alloc(j);
}

pub fn alloc<T>(&self, val: T) -> &mut T[src]

Allocate an object in this Bump and return an exclusive reference to it.

Panics

Panics if reserving space for T would cause an overflow.

Example

let bump = bumpalo::Bump::new();
let x = bump.alloc("hello");
assert_eq!(*x, "hello");

pub fn alloc_with<F, T>(&self, f: F) -> &mut T where
    F: FnOnce() -> T, 
[src]

Pre-allocate space for an object in this Bump, initializes it using the closure, then returns an exclusive reference to it.

Calling bump.alloc(x) is essentially equivalent to calling bump.alloc_with(|| x). However if you use alloc_with, then the closure will not be invoked until after allocating space for storing x on the heap.

This can be useful in certain edge-cases related to compiler optimizations. When evaluating bump.alloc(x), semantically x is first put on the stack and then moved onto the heap. In some cases, the compiler is able to optimize this into constructing x directly on the heap, however in many cases it does not.

The function alloc_with tries to help the compiler be smarter. In most cases doing bump.alloc_with(|| x) on release mode will be enough to help the compiler to realize this optimization is valid and construct x directly onto the heap.

Warning

This function critically depends on compiler optimizations to achieve its desired effect. This means that it is not an effective tool when compiling without optimizations on.

Even when optimizations are on, this function does not guarantee that the value is constructed on the heap. To the best of our knowledge no such guarantee can be made in stable Rust as of 1.33.

Panics

Panics if reserving space for T would cause an overflow.

Example

let bump = bumpalo::Bump::new();
let x = bump.alloc_with(|| "hello");
assert_eq!(*x, "hello");

pub fn alloc_slice_copy<T>(&self, src: &[T]) -> &mut [T] where
    T: Copy
[src]

Copy a slice into this Bump and return an exclusive reference to the copy.

Panics

Panics if reserving space for the slice would cause an overflow.

Example

let bump = bumpalo::Bump::new();
let x = bump.alloc_slice_copy(&[1, 2, 3]);
assert_eq!(x, &[1, 2, 3]);

pub fn alloc_slice_clone<T>(&self, src: &[T]) -> &mut [T] where
    T: Clone
[src]

Clone a slice into this Bump and return an exclusive reference to the clone. Prefer alloc_slice_copy if T is Copy.

Panics

Panics if reserving space for the slice would cause an overflow.

Example

#[derive(Clone, Debug, Eq, PartialEq)]
struct Sheep {
    name: String,
}

let originals = vec![
    Sheep { name: "Alice".into() },
    Sheep { name: "Bob".into() },
    Sheep { name: "Cathy".into() },
];

let bump = bumpalo::Bump::new();
let clones = bump.alloc_slice_clone(&originals);
assert_eq!(originals, clones);

pub fn alloc_layout(&self, layout: Layout) -> NonNull<u8>[src]

Allocate space for an object with the given Layout.

The returned pointer points at uninitialized memory, and should be initialized with std::ptr::write.

pub unsafe fn each_allocated_chunk<F>(&mut self, f: F) where
    F: for<'a> FnMut(&'a [u8]), 
[src]

Call f on each chunk of allocated memory that this arena has bump allocated into.

f is invoked in order of allocation: oldest chunks first, newest chunks last.

Safety

Because this method takes &mut self, we know that the bump arena reference is unique and therefore there aren't any active references to any of the objects we've allocated in it either. This potential aliasing of exclusive references is one common footgun for unsafe code that we don't need to worry about here.

However, there could be regions of uninitialized memory used as padding between allocations. Reading uninitialized memory is big time undefined behavior!

The only way to guarantee that there is no padding between allocations or within allocated objects is if all of these properties hold:

  1. Every object allocated in this arena has the same alignment.
  2. Every object's size is a multiple of its alignment.
  3. None of the objects allocated in this arena contain any internal padding.

If you want to use this each_allocated_chunk method, it is your responsibility to ensure that these properties hold!

Example

let mut bump = bumpalo::Bump::new();

// Allocate a bunch of things in this bump arena, potentially causing
// additional memory chunks to be reserved.
for i in 0..10000 {
    bump.alloc(i);
}

// Iterate over each chunk we've bump allocated into. This is safe
// because we have only allocated `i32` objects in this arena.
unsafe {
    bump.each_allocated_chunk(|ch| {
        println!("Used a chunk that is {} bytes long", ch.len());
    });
}

Trait Implementations

impl Drop for Bump[src]

impl Default for Bump[src]

impl Send for Bump[src]

impl Debug for Bump[src]

Auto Trait Implementations

impl Unpin for Bump

impl !Sync for Bump

impl !RefUnwindSafe for Bump

impl !UnwindSafe for Bump

Blanket Implementations

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]