Skip to main content

BoundedAllocator

Struct BoundedAllocator 

Source
pub struct BoundedAllocator<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> { /* private fields */ }
Expand description

Static pre-allocated bounded global allocator.

Generic parameters

  • MAX_BLOCKS — maximum number of simultaneously-live blocks.
  • BLOCK_SIZE — maximum bytes per allocation. Should be a multiple of 64 to avoid intra-block padding.
  • BITMAP_WORDS — must be (MAX_BLOCKS + 63) / 64. Use the declare_global_allocator! / bounded_allocator! macros to compute it automatically.

Implementations§

Source§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

Source

pub const fn new() -> Self

Construct a fresh allocator. Intended for use as a static initialiser.

All bitmap words are initialised to all-ones, meaning every block is free. The few tail bits past MAX_BLOCKS in the last word are also set, but the bit-scan refuses to allocate them (block index >= MAX_BLOCKS rejection).

Source

pub fn lock(&self)

Engage lock-after-init mode. Every subsequent alloc call panics immediately. One-way: there is no unlock method.

Source

pub fn is_locked(&self) -> bool

Is the allocator locked? See Self::lock.

Source

pub fn alloc_count(&self) -> usize

Total successful alloc calls since process start.

Examples found in repository?
examples/fail_closed.rs (line 48)
33fn main() {
34    println!("taktora-bounded-alloc fail_closed demo");
35    println!("arena: {MAX_BLOCKS} blocks × {BLOCK_SIZE} bytes");
36    println!(
37        "blocks already in use after Rust runtime startup: {}",
38        ALLOC.live_blocks()
39    );
40    println!();
41
42    let mut held: Vec<Box<[u8; 1024]>> = Vec::new();
43    for i in 0_u32..64 {
44        let b: Box<[u8; 1024]> = Box::new([(i & 0xff) as u8; 1024]);
45        held.push(b);
46        println!(
47            "iter {i}: alloc_count={}, live={}, peak={}, held={}",
48            ALLOC.alloc_count(),
49            ALLOC.live_blocks(),
50            ALLOC.peak_blocks_used(),
51            held.len()
52        );
53    }
54
55    // Unreachable: an allocation past the cap returns null, and
56    // Rust's default alloc_error_handler aborts the process.
57    println!("unexpectedly reached end of main (cap was not exhausted)");
58}
Source

pub fn dealloc_count(&self) -> usize

Total dealloc calls since process start.

Source

pub fn peak_blocks_used(&self) -> usize

High-water mark of simultaneously-live blocks.

Examples found in repository?
examples/fail_closed.rs (line 50)
33fn main() {
34    println!("taktora-bounded-alloc fail_closed demo");
35    println!("arena: {MAX_BLOCKS} blocks × {BLOCK_SIZE} bytes");
36    println!(
37        "blocks already in use after Rust runtime startup: {}",
38        ALLOC.live_blocks()
39    );
40    println!();
41
42    let mut held: Vec<Box<[u8; 1024]>> = Vec::new();
43    for i in 0_u32..64 {
44        let b: Box<[u8; 1024]> = Box::new([(i & 0xff) as u8; 1024]);
45        held.push(b);
46        println!(
47            "iter {i}: alloc_count={}, live={}, peak={}, held={}",
48            ALLOC.alloc_count(),
49            ALLOC.live_blocks(),
50            ALLOC.peak_blocks_used(),
51            held.len()
52        );
53    }
54
55    // Unreachable: an allocation past the cap returns null, and
56    // Rust's default alloc_error_handler aborts the process.
57    println!("unexpectedly reached end of main (cap was not exhausted)");
58}
Source

pub fn live_blocks(&self) -> usize

Currently-live block count.

Examples found in repository?
examples/fail_closed.rs (line 38)
33fn main() {
34    println!("taktora-bounded-alloc fail_closed demo");
35    println!("arena: {MAX_BLOCKS} blocks × {BLOCK_SIZE} bytes");
36    println!(
37        "blocks already in use after Rust runtime startup: {}",
38        ALLOC.live_blocks()
39    );
40    println!();
41
42    let mut held: Vec<Box<[u8; 1024]>> = Vec::new();
43    for i in 0_u32..64 {
44        let b: Box<[u8; 1024]> = Box::new([(i & 0xff) as u8; 1024]);
45        held.push(b);
46        println!(
47            "iter {i}: alloc_count={}, live={}, peak={}, held={}",
48            ALLOC.alloc_count(),
49            ALLOC.live_blocks(),
50            ALLOC.peak_blocks_used(),
51            held.len()
52        );
53    }
54
55    // Unreachable: an allocation past the cap returns null, and
56    // Rust's default alloc_error_handler aborts the process.
57    println!("unexpectedly reached end of main (cap was not exhausted)");
58}
Source

pub const fn capacity_bytes(&self) -> usize

Total arena bytes addressed by this allocator.

Trait Implementations§

Source§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> Default for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> GlobalAlloc for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

Source§

unsafe fn alloc(&self, layout: Layout) -> *mut u8

Allocates memory as described by the given layout. Read more
Source§

unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout)

Deallocates the block of memory at the given ptr pointer with the given layout. Read more
1.28.0 · Source§

unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8

Behaves like alloc, but also ensures that the contents are set to zero before being returned. Read more
1.28.0 · Source§

unsafe fn realloc( &self, ptr: *mut u8, layout: Layout, new_size: usize, ) -> *mut u8

Shrinks or grows a block of memory to the given new_size in bytes. The block is described by the given ptr pointer and layout. Read more

Auto Trait Implementations§

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> !Freeze for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> !RefUnwindSafe for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> Send for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> Sync for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> Unpin for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> UnsafeUnpin for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

§

impl<const MAX_BLOCKS: usize, const BLOCK_SIZE: usize, const BITMAP_WORDS: usize> UnwindSafe for BoundedAllocator<MAX_BLOCKS, BLOCK_SIZE, BITMAP_WORDS>

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.