UnsafeStalloc

Struct UnsafeStalloc 

Source
pub struct UnsafeStalloc<const L: usize, const B: usize>(/* private fields */)
where
    Align<B>: Alignment;
Expand description

A wrapper around Stalloc that implements both Sync and GlobalAlloc.

This type is unsafe to create, because it does not prevent data races. Therefore, it is encouraged to only use it in single-threaded environments.

Implementations§

Source§

impl<const L: usize, const B: usize> UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source

pub const unsafe fn new() -> Self

§Safety

UnsafeStalloc does not prevent data races. It is strongly recommend to only use it in a single-threaded environment.

§Examples
use stalloc::UnsafeStalloc;

let alloc = unsafe { UnsafeStalloc::<200, 8>::new() };
Examples found in repository?
examples/fast_vectors.rs (line 7)
7static GLOBAL: UnsafeStalloc<1000, 4> = unsafe { UnsafeStalloc::new() };
Source§

impl<const L: usize, const B: usize> UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source

pub const fn chain<T>(self, next: &T) -> AllocChain<'_, Self, T>
where Self: Sized,

Creates a new AllocChain containing this allocator and next.

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> ChainableAlloc for UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source§

fn claims(&self, ptr: *mut u8, layout: Layout) -> bool

Tests whether a certain allocation belongs to this allocator. This is called when using deallocate() and related functions in order to determine which allocator needs to free the pointer.
Source§

impl<const L: usize, const B: usize> Debug for UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<const L: usize, const B: usize> Deref for UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source§

type Target = Stalloc<L, B>

The resulting type after dereferencing.
Source§

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

Dereferences the value.
Source§

impl<const L: usize, const B: usize> GlobalAlloc for UnsafeStalloc<L, B>
where Align<B>: Alignment,

Source§

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

Allocates memory as described by the given layout. Read more
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
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
Source§

unsafe fn realloc( &self, ptr: *mut u8, old_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
Source§

impl<const L: usize, const B: usize> Sync for UnsafeStalloc<L, B>
where Align<B>: Alignment,

Auto Trait Implementations§

§

impl<const L: usize, const B: usize> !Freeze for UnsafeStalloc<L, B>

§

impl<const L: usize, const B: usize> !RefUnwindSafe for UnsafeStalloc<L, B>

§

impl<const L: usize, const B: usize> !Send for UnsafeStalloc<L, B>

§

impl<const L: usize, const B: usize> !Unpin for UnsafeStalloc<L, B>

§

impl<const L: usize, const B: usize> !UnwindSafe for UnsafeStalloc<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.