Skip to main content

ArenaAllocator

Struct ArenaAllocator 

Source
pub struct ArenaAllocator<A: Allocator> { /* private fields */ }
Expand description

A block-based allocator that frees all memory at once.

ArenaAllocator<A> is generic over its backing allocator A which is called for each individual block allocation and for every block deallocation during reset.

The internal state uses Cell to allow shared (&self) allocation, which is necessary so that multiple collections can borrow the same arena simultaneously.

§Dropping

Dropping an ArenaAllocator automatically calls reset, returning all memory to the backing allocator.

Implementations§

Source§

impl<A: Allocator> ArenaAllocator<A>

Source

pub fn new(backing: A) -> Self

Creates a new, empty arena backed by backing.

No memory is allocated from backing until the first call to alloc.

Examples found in repository?
examples/arena_vec.rs (line 7)
5fn main() {
6    let sys = SystemAllocator;
7    let arena = ArenaAllocator::new(&sys);
8
9    let mut numbers = ExVec::new(&arena);
10
11    for i in 1..=100 {
12        numbers.push(i);
13    }
14
15    println!("Sum: {}", numbers.iter().sum::<i32>());
16    
17    arena.reset();
18    println!("Arena memory reclaimed. Allocations count was: {}", arena.alloc_count());
19}
More examples
Hide additional examples
examples/full.rs (line 25)
9fn main() {
10    let sys = CountingAllocator::new(SystemAllocator);
11    
12    println!("=== ExBox & SystemAllocator ===");
13    {
14        let b = ExBox::new(42, &sys).expect("Failed to alloc Box");
15        println!("Box value: {}", *b);
16    }
17    
18    let stats = sys.stats();
19    println!("Allocated: {} bytes", stats.bytes_allocated);
20    println!("Deallocated: {} bytes", stats.bytes_freed);
21    println!("Live bytes: {}\n", stats.bytes_live);
22
23    println!("=== ExVec & Arena (Linear Allocation) ===");
24    {
25        let arena = ArenaAllocator::new(&sys);
26        
27        let mut v = ExVec::new(&arena);
28        for i in 0..5 {
29            v.push(i * 10);
30        }
31        println!("Vec: {:?}", v.as_slice());
32        
33        arena.reset();
34        println!("Arena reset performed");
35    }
36
37    println!("\n=== ExString & Pool (Fixed Size Blocks) ===");
38    {
39        let pool = PoolAllocator::typed::<[u8; 64]>(&sys, 10)
40            .expect("Failed to create Pool");
41        
42        let mut s = ExString::new(&pool);
43        s.push_str("Hello from ZigZag!");
44        
45        println!("String in Pool: {}", s.as_str());
46        println!("Pool free slots: {}", pool.free_count());
47    }
48
49    println!("\n=== Final Global Stats ===");
50    let final_stats = sys.stats();
51    println!("Total count of alloc() calls: {}", final_stats.allocs);
52    println!("Total count of dealloc() calls: {}", final_stats.deallocs);
53    println!("Total bytes allocated: {}", final_stats.bytes_allocated);
54    println!("Total bytes freed: {}", final_stats.bytes_freed);
55    println!("Current leak/live size: {} bytes", final_stats.bytes_live);
56}
Source

pub fn alloc_count(&self) -> usize

Returns the number of live allocations currently managed by this arena.

The counter is reset to zero by reset or reset_zeroed.

Examples found in repository?
examples/arena_vec.rs (line 18)
5fn main() {
6    let sys = SystemAllocator;
7    let arena = ArenaAllocator::new(&sys);
8
9    let mut numbers = ExVec::new(&arena);
10
11    for i in 1..=100 {
12        numbers.push(i);
13    }
14
15    println!("Sum: {}", numbers.iter().sum::<i32>());
16    
17    arena.reset();
18    println!("Arena memory reclaimed. Allocations count was: {}", arena.alloc_count());
19}
Source

pub fn reset(&self)

Releases all memory blocks managed by this arena back to the backing allocator.

After this call, all pointers previously returned by alloc are invalid.

§Safety

The caller must ensure that no pointers previously obtained from this arena are used after reset returns (use-after-free).

Examples found in repository?
examples/arena_vec.rs (line 17)
5fn main() {
6    let sys = SystemAllocator;
7    let arena = ArenaAllocator::new(&sys);
8
9    let mut numbers = ExVec::new(&arena);
10
11    for i in 1..=100 {
12        numbers.push(i);
13    }
14
15    println!("Sum: {}", numbers.iter().sum::<i32>());
16    
17    arena.reset();
18    println!("Arena memory reclaimed. Allocations count was: {}", arena.alloc_count());
19}
More examples
Hide additional examples
examples/full.rs (line 33)
9fn main() {
10    let sys = CountingAllocator::new(SystemAllocator);
11    
12    println!("=== ExBox & SystemAllocator ===");
13    {
14        let b = ExBox::new(42, &sys).expect("Failed to alloc Box");
15        println!("Box value: {}", *b);
16    }
17    
18    let stats = sys.stats();
19    println!("Allocated: {} bytes", stats.bytes_allocated);
20    println!("Deallocated: {} bytes", stats.bytes_freed);
21    println!("Live bytes: {}\n", stats.bytes_live);
22
23    println!("=== ExVec & Arena (Linear Allocation) ===");
24    {
25        let arena = ArenaAllocator::new(&sys);
26        
27        let mut v = ExVec::new(&arena);
28        for i in 0..5 {
29            v.push(i * 10);
30        }
31        println!("Vec: {:?}", v.as_slice());
32        
33        arena.reset();
34        println!("Arena reset performed");
35    }
36
37    println!("\n=== ExString & Pool (Fixed Size Blocks) ===");
38    {
39        let pool = PoolAllocator::typed::<[u8; 64]>(&sys, 10)
40            .expect("Failed to create Pool");
41        
42        let mut s = ExString::new(&pool);
43        s.push_str("Hello from ZigZag!");
44        
45        println!("String in Pool: {}", s.as_str());
46        println!("Pool free slots: {}", pool.free_count());
47    }
48
49    println!("\n=== Final Global Stats ===");
50    let final_stats = sys.stats();
51    println!("Total count of alloc() calls: {}", final_stats.allocs);
52    println!("Total count of dealloc() calls: {}", final_stats.deallocs);
53    println!("Total bytes allocated: {}", final_stats.bytes_allocated);
54    println!("Total bytes freed: {}", final_stats.bytes_freed);
55    println!("Current leak/live size: {} bytes", final_stats.bytes_live);
56}
Source

pub fn reset_zeroed(&self)

Zeroes the user-data portion of every block before releasing them.

Equivalent to reset but erases sensitive data first using SIMD-accelerated zero-fill.

§Safety

Same as reset: all previously returned pointers are invalidated.

Trait Implementations§

Source§

impl<A: Allocator> Allocator for ArenaAllocator<A>

Source§

unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>>

Allocates a new block, prepends a [Header], and returns a pointer to the user-data region.

Internally calls the backing allocator for a single block large enough to hold both the Header and the user data (with proper alignment padding in between), then links the new block at the head of the internal list.

§Safety
  • layout.size() must be greater than zero.
  • The returned pointer is valid until the next call to reset or until the arena is dropped.
Source§

unsafe fn dealloc(&self, _: NonNull<u8>, _: Layout)

No-op. Arena memory cannot be freed individually.

To release all memory, call reset or drop the arena.

§Safety

Even though this method is a no-op, callers must not use ptr after calling dealloc — the pointer will become dangling once reset is eventually called.

Source§

impl<A: Allocator> ArenaExt for ArenaAllocator<A>

Source§

unsafe fn alloc_zeroed(&self, layout: Layout) -> Option<NonNull<u8>>

Allocates a block and zero-fills the user-data region with SIMD.

Delegates to alloc and then applies a SIMD zero-fill, which is faster than a scalar loop for large allocations.

§Safety
  • layout.size() must be greater than zero.
  • The returned pointer becomes invalid after reset or when the arena is dropped.
Source§

impl<A: Allocator> Drop for ArenaAllocator<A>

Source§

fn drop(&mut self)

Releases all managed blocks by calling reset.

Auto Trait Implementations§

§

impl<A> !Freeze for ArenaAllocator<A>

§

impl<A> !RefUnwindSafe for ArenaAllocator<A>

§

impl<A> !Send for ArenaAllocator<A>

§

impl<A> !Sync for ArenaAllocator<A>

§

impl<A> Unpin for ArenaAllocator<A>
where A: Unpin,

§

impl<A> UnsafeUnpin for ArenaAllocator<A>
where A: UnsafeUnpin,

§

impl<A> UnwindSafe for ArenaAllocator<A>
where A: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

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

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.