StallocGuard

Struct StallocGuard 

Source
pub struct StallocGuard<'a, const L: usize, const B: usize>
where Align<B>: Alignment,
{ /* private fields */ }
Expand description

A lock around SyncStalloc. Constructing this type is proof that the user holds an exclusive lock on the inner UnsafeStalloc. When this falls out of scope, the SyncStalloc is unlocked.

This is effectively a reimplementation of std::sync::MutexGuard.

Methods from Deref<Target = Stalloc<L, B>>§

Source

pub fn is_oom(&self) -> bool

Checks if the allocator is completely out of memory. If this is false, then you are guaranteed to be able to allocate a layout with a size and alignment of B bytes. This runs in O(1).

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<200, 8>::new();
assert!(!alloc.is_oom());
let ptr = unsafe { alloc.allocate_blocks(200, 1).unwrap() };
assert!(alloc.is_oom());
Source

pub fn is_empty(&self) -> bool

Checks if the allocator is empty. If this is true, then you are guaranteed to be able to allocate a layout with a size of B * L bytes and an alignment of B bytes. If this is false, then this is guaranteed to be impossible. This runs in O(1).

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<60, 4>::new();
assert!(alloc.is_empty());

let ptr = unsafe { alloc.allocate_blocks(60, 1).unwrap() };
assert!(!alloc.is_empty());

unsafe { alloc.deallocate_blocks(ptr, 60) };
assert!(alloc.is_empty());
Source

pub unsafe fn clear(&self)

§Safety

Calling this function immediately invalidates all pointers into the allocator. Calling deallocate_blocks() with an invalidated pointer will result in the free list being corrupted.

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<60, 4>::new();

let ptr1 = unsafe { alloc.allocate_blocks(20, 1) }.unwrap();
let ptr2 = unsafe { alloc.allocate_blocks(20, 1) }.unwrap();
let ptr3 = unsafe { alloc.allocate_blocks(20, 1) }.unwrap();

unsafe { alloc.clear() }; // invalidate all allocated pointers

assert!(alloc.is_empty());
Examples found in repository?
examples/fast_vectors.rs (line 25)
9fn main() {
10	let start = Instant::now();
11	for _ in 0..10_000_000 {
12		let mut a = vec![];
13		let mut b = vec![];
14		for i in 0..10 {
15			a.push(i);
16			b.push(i);
17		}
18
19		mem::forget(a);
20		mem::forget(b);
21
22		// By clearing the global allocator, we can quickly drop both vectors together.
23		// SAFETY: There are no more active allocations into `GLOBAL`.
24		unsafe {
25			GLOBAL.clear();
26		}
27	}
28
29	println!("Elapsed: {}ms", start.elapsed().as_millis());
30}
Source

pub unsafe fn allocate_blocks( &self, size: usize, align: usize, ) -> Result<NonNull<u8>, AllocError>

Tries to allocate count blocks. If the allocation succeeds, a pointer is returned. This function never allocates more than necessary. Note that align is measured in units of B.

§Safety

size must be nonzero, and align must be a power of 2 in the range 1..=2^29 / B.

§Errors

Will return AllocError if the allocation was unsuccessful, in which case this function was a no-op.

§Examples
use stalloc::Stalloc;

const BLOCK_SIZE: usize = 4;
let alloc = Stalloc::<10, BLOCK_SIZE>::new();

let ptr = unsafe { alloc.allocate_blocks(10, 1) }.unwrap();
unsafe { ptr.write_bytes(42, 10 * BLOCK_SIZE) };

assert!(alloc.is_oom());
Source

pub unsafe fn deallocate_blocks(&self, ptr: NonNull<u8>, size: usize)

Deallocates a pointer. This function always succeeds.

§Safety

ptr must point to an allocation, and size must be the number of blocks in the allocation. That is, size is always in 1..=L.

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<100, 16>::new();

let ptr = unsafe { alloc.allocate_blocks(100, 1) }.unwrap();
assert!(alloc.is_oom());

unsafe { alloc.deallocate_blocks(ptr, 100) };
assert!(alloc.is_empty());
Source

pub unsafe fn shrink_in_place( &self, ptr: NonNull<u8>, old_size: usize, new_size: usize, )

Shrinks the allocation. This function always succeeds and never reallocates.

§Safety

ptr must point to a valid allocation of old_size blocks, and new_size must be in 1..old_size.

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<100, 16>::new();

let ptr = unsafe { alloc.allocate_blocks(100, 1) }.unwrap();
assert!(alloc.is_oom());

// shrink the allocation from 100 to 90 blocks
unsafe { alloc.shrink_in_place(ptr, 100, 90) };
assert!(!alloc.is_oom());
Source

pub unsafe fn grow_in_place( &self, ptr: NonNull<u8>, old_size: usize, new_size: usize, ) -> Result<(), AllocError>

Tries to grow the current allocation in-place. If that isn’t possible, this function is a no-op.

§Safety

ptr must point to a valid allocation of old_size blocks. Also, new_size > old_size.

§Errors

Will return AllocError if the grow was unsuccessful, in which case this function was a no-op.

§Examples
use stalloc::Stalloc;

let alloc = Stalloc::<100, 16>::new();

let ptr = unsafe { alloc.allocate_blocks(25, 1) }.unwrap();
assert!(!alloc.is_oom());

// grow the allocation from 25 to 100 blocks
unsafe { alloc.grow_in_place(ptr, 25, 100) }.unwrap();
assert!(alloc.is_oom());
Source

pub unsafe fn grow_up_to( &self, ptr: NonNull<u8>, old_size: usize, new_size: usize, ) -> usize

Tries to grow the current allocation in-place. If that isn’t possible, the allocator grows by as much as it is able to, and the new length of the allocation is returned. The new length is guaranteed to be in the range old_size..=new_size.

§Safety

ptr must point to a valid allocation of old_size blocks. Also, new_size > old_size.

§Examples
use stalloc::Stalloc;

let alloc1 = Stalloc::<7, 4>::new();
unsafe {
    let ptr = alloc1.allocate_blocks(3, 1).unwrap(); // allocate 3 blocks
    let new_size = alloc1.grow_up_to(ptr, 3, 9999); // try to grow to a ridiculous amount
    assert_eq!(new_size, 7); // can only grow up to 7
}

let alloc2 = Stalloc::<21, 16>::new();
unsafe {
    let ptr = alloc2.allocate_blocks(9, 1).unwrap(); // allocate 9 blocks
    let new_size = alloc2.grow_up_to(ptr, 9, 21);
    assert_eq!(new_size, 21); // grow was successful
}

Trait Implementations§

Source§

impl<const L: usize, const B: usize> Deref for StallocGuard<'_, L, B>
where Align<B>: Alignment,

Source§

type Target = UnsafeStalloc<L, B>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<'a, const L: usize, const B: usize> Freeze for StallocGuard<'a, L, B>

§

impl<'a, const L: usize, const B: usize> !RefUnwindSafe for StallocGuard<'a, L, B>

§

impl<'a, const L: usize, const B: usize> !Send for StallocGuard<'a, L, B>

§

impl<'a, const L: usize, const B: usize> !Sync for StallocGuard<'a, L, B>

§

impl<'a, const L: usize, const B: usize> Unpin for StallocGuard<'a, L, B>

§

impl<'a, const L: usize, const B: usize> !UnwindSafe for StallocGuard<'a, L, B>

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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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.