pub struct WithAllocationInfo<A> { /* private fields */ }Expand description
Wrapper around an allocator, that gathers stats about the underlying store while allocating.
The allocator_api2 design intentionally avoids generics in its result types. Allocations in
the bump arena however provide some auxiliary information such as the usage level of the bump
before and after an allocation (at least a snapshot of it for a Sync allocator). This
information can be especially useful in case of an allocation failure but gather it separately
would be racy. Allocating with this wrapper avoids the race.
For these use cases you can replace the allocator handle with this wrapper. The wrapper is equivalent to the underlying allocator.
§Usage
use static_alloc::allocator_api2::WithAllocationInfo;
use static_alloc::bump::Bump;§Design
Interestingly, we could also provide per-call allocator configuration. For a Bump shared
between threads for instance there is an inner loop around a fallible CAS. A parameter could
constrain this loop to exit early on a case-by-case basis. It does not make too much sense to
enforce it for all allocations in the arena. You would often prefer to use a non-racy
thread-local arena in those cases (please open an issue if you have a use case). A handle
wrapper on the other hand would provide surgical amounts of control.
Implementations§
Source§impl<'lt, A: ?Sized> WithAllocationInfo<&'lt A>
impl<'lt, A: ?Sized> WithAllocationInfo<&'lt A>
Sourcepub fn new(arena: &'lt A) -> Self
pub fn new(arena: &'lt A) -> Self
Wrap an arena to gather stats.
This does not constrain the type A. However, it can only be sensibly used with a
Bump or BumpSlice or the unsync
BumpSlice. It does not work with unsync’s Bump due to
current design differences. (It is implemented with Deref into a BumpSlice instead of a
view used for both. This will post-monomorphization error which we do not want to hide).
Source§impl<A> WithAllocationInfo<A>
impl<A> WithAllocationInfo<A>
Sourcepub fn last_observed_level(&self) -> Level
pub fn last_observed_level(&self) -> Level
Query the consumed level observed by the last allocation call.
The value is updated both on success and failure.
§Usage
You will get information about the consumed bytes with each attempted allocation.
use static_alloc::allocator_api2::WithAllocationInfo;
use static_alloc::bump::Bump;
use allocator_api2::vec::Vec;
let arena = Bump::<[usize; 4]>::uninit();
let hdl = WithAllocationInfo::new(&arena);
let mut vec = Vec::<u32, _>::with_capacity_in(1, hdl);
assert_eq!(vec.allocator().last_observed_level().byte_offset(), 4);
// This will not fit, and fail to allocate.
vec.try_reserve(32);
assert_eq!(vec.allocator().last_observed_level().byte_offset(), 4);
// This will, reallocating the vector.
vec.try_reserve_exact(2);
assert_eq!(vec.allocator().last_observed_level().byte_offset(), 12);The information is updated also when the arena is used concurrently for another purpose, too.
use static_alloc::allocator_api2::WithAllocationInfo;
use static_alloc::bump::Bump;
use allocator_api2::vec::Vec;
let arena = Bump::<[usize; 4]>::uninit();
let hdl = WithAllocationInfo::new(&arena);
let mut vec = Vec::<u32, _>::new_in(hdl);
let _ = arena.leak(0u32);
// Afterwards exactly three `u32` allocator, the one leaked and the 2 reserved.
vec.try_reserve_exact(2);
assert_eq!(vec.allocator().last_observed_level().byte_offset(), 12);Sourcepub fn last_allocation_start(&self) -> Level
pub fn last_allocation_start(&self) -> Level
Get the Level at which the last successful allocation sits.
This is provided for all allocations, sized and unsized.
§Usage
use static_alloc::allocator_api2::WithAllocationInfo;
use static_alloc::bump::Bump;
use allocator_api2::vec::Vec;
let arena = Bump::<[usize; 4]>::uninit();
let hdl = WithAllocationInfo::new(&arena);
let mut vec = Vec::<u32, _>::with_capacity_in(1, hdl);
assert_eq!(vec.allocator().last_allocation_start().byte_offset(), 0);
// This will reallocate the vector, after the previous one.
vec.try_reserve_exact(2);
assert_eq!(vec.allocator().last_allocation_start().byte_offset(), 4);Trait Implementations§
Source§impl<T> Allocator for WithAllocationInfo<&Bump<T>>
impl<T> Allocator for WithAllocationInfo<&Bump<T>>
Source§fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
Source§unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
ptr. Read moreSource§unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn shrink( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Source§fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocate, but also ensures that the returned memory is zero-initialized. Read moreSource§unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Source§impl Allocator for WithAllocationInfo<&BumpSlice>
impl Allocator for WithAllocationInfo<&BumpSlice>
Source§fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
Source§unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
ptr. Read moreSource§unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn shrink( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Source§fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocate, but also ensures that the returned memory is zero-initialized. Read moreSource§unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn grow( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Source§impl Allocator for WithAllocationInfo<&BumpSlice>
impl Allocator for WithAllocationInfo<&BumpSlice>
Source§fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
Source§unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
unsafe fn deallocate(&self, _: NonNull<u8>, _: Layout)
ptr. Read moreSource§unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError>
unsafe fn shrink( &self, ptr: NonNull<u8>, old_layout: Layout, new_layout: Layout, ) -> Result<NonNull<[u8]>, AllocError>
Source§fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>
allocate, but also ensures that the returned memory is zero-initialized. Read more