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>>§
Sourcepub fn is_oom(&self) -> bool
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());Sourcepub fn is_empty(&self) -> bool
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());Sourcepub unsafe fn clear(&self)
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?
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}Sourcepub unsafe fn allocate_blocks(
&self,
size: usize,
align: usize,
) -> Result<NonNull<u8>, AllocError>
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());Sourcepub unsafe fn deallocate_blocks(&self, ptr: NonNull<u8>, size: usize)
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());Sourcepub unsafe fn shrink_in_place(
&self,
ptr: NonNull<u8>,
old_size: usize,
new_size: usize,
)
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());Sourcepub unsafe fn grow_in_place(
&self,
ptr: NonNull<u8>,
old_size: usize,
new_size: usize,
) -> Result<(), AllocError>
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());Sourcepub unsafe fn grow_up_to(
&self,
ptr: NonNull<u8>,
old_size: usize,
new_size: usize,
) -> usize
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
}