pub trait BStackAllocator: Sized {
type Error: Debug + Display;
type Allocated<'a>: Copy + TryInto<BStackSlice<'a, Self>, Error: Debug + Display>
where Self: 'a;
// Required methods
fn stack(&self) -> &BStack ⓘ;
fn into_stack(self) -> BStack ⓘ;
fn alloc(&self, len: u64) -> Result<Self::Allocated<'_>, Self::Error>;
fn realloc<'a>(
&'a self,
handle: Self::Allocated<'a>,
new_len: u64,
) -> Result<Self::Allocated<'a>, Self::Error>;
// Provided methods
fn dealloc(&self, _handle: Self::Allocated<'_>) -> Result<(), Self::Error> { ... }
fn len(&self) -> Result<u64> { ... }
fn is_empty(&self) -> Result<bool> { ... }
}Expand description
A trait for types that own a BStack and manage contiguous byte regions
within its payload.
§Ownership model
An implementor takes ownership of a BStack. BStackSlice handles
produced by alloc borrow the allocator for lifetime '_,
which prevents the allocator from being consumed by
into_stack while any slice is alive. The canonical
pattern:
struct MyAllocator { stack: BStack }
impl BStackAllocator for MyAllocator {
fn stack(&self) -> &BStack { &self.stack }
fn alloc(&self, len: u64) -> io::Result<BStackSlice<'_, Self>> { ... }
fn realloc<'a>(&'a self, slice: BStackSlice<'a, Self>, new_len: u64)
-> io::Result<BStackSlice<'a, Self>> { ... }
fn into_stack(self) -> BStack { self.stack }
}§Crash consistency
Implementors must document the crash-consistency class of each
operation they provide. As a rule of thumb: if every method maps to a
single BStack call it is crash-safe by inheritance; if any method
issues two or more calls it requires an explicit recovery design.
§See also
BStackBulkAllocator — extension trait that adds atomic bulk
alloc_bulk and
dealloc_bulk methods for
allocators that can batch multiple operations into a single I/O call.
Required Associated Types§
Sourcetype Error: Debug + Display
type Error: Debug + Display
The error type returned by alloc,
realloc, dealloc,
alloc_bulk, and
dealloc_bulk.
Must implement fmt::Debug and fmt::Display so that errors can be
printed and propagated with ?.
All allocators provided by this library set Error = io::Error.
Third-party implementations may use a richer type, but are encouraged
to follow the same convention for interoperability.
Sourcetype Allocated<'a>: Copy + TryInto<BStackSlice<'a, Self>, Error: Debug + Display>
where
Self: 'a
type Allocated<'a>: Copy + TryInto<BStackSlice<'a, Self>, Error: Debug + Display> where Self: 'a
The handle type returned by alloc and
realloc, and accepted by realloc
and dealloc.
Must be Copy (cheap to pass by value) and convertible to
BStackSlice via TryInto for generic I/O use. The conversion
error must implement fmt::Debug and fmt::Display.
Simple allocators set type Allocated<'a> = BStackSlice<'a, Self>.
Richer allocators may embed additional metadata in a newtype whose
TryInto implementation is always infallible.
All allocators provided by this library set type Allocated<'a> = BStackSlice<'a, Self>,
which have blanket implementations by rust since impl<T, U> TryInto<U> for T where T: Into<U> and impl<T, U> Into<U> for T are provided
by the standard library.
Required Methods§
Sourcefn stack(&self) -> &BStack ⓘ
fn stack(&self) -> &BStack ⓘ
Return a shared reference to the underlying BStack.
Note: Bstack does not require mutability for any of its operations,
and directly mutating the stack without the knowledge of the allocator
risks violating invariants. Therefore, use this method with caution
and prefer methods on BStackSlice that delegate to the stack internally.
Sourcefn into_stack(self) -> BStack ⓘ
fn into_stack(self) -> BStack ⓘ
Consume the allocator and return the underlying BStack.
This method takes self by value, so it can only be called once all
BStackSlice handles have been dropped — the borrow checker enforces
this because slices borrow &'a Self.
Sourcefn alloc(&self, len: u64) -> Result<Self::Allocated<'_>, Self::Error>
fn alloc(&self, len: u64) -> Result<Self::Allocated<'_>, Self::Error>
Allocate len zero-initialised bytes.
Returns a BStackSlice handle covering the newly allocated region.
The region is durably synced before returning. len = 0 is valid.
§Errors
Returns Self::Error on failure.
Sourcefn realloc<'a>(
&'a self,
handle: Self::Allocated<'a>,
new_len: u64,
) -> Result<Self::Allocated<'a>, Self::Error>
fn realloc<'a>( &'a self, handle: Self::Allocated<'a>, new_len: u64, ) -> Result<Self::Allocated<'a>, Self::Error>
Resize the region described by handle to new_len bytes.
Returns a (possibly different) handle covering the resized region.
The lifetime 'a ties the returned handle to the same borrow as the
input handle and the allocator.
§Slice origin requirement
handle must have been returned directly by alloc
or by a prior call to realloc on this same allocator
instance. Passing an arbitrary sub-slice obtained via
BStackSlice::subslice, BStackSlice::subslice_range, or a
manually constructed BStackSlice::new is not supported and may
corrupt the allocator’s internal state.
§Errors
Returns Self::Error on failure, including when the implementation does
not support reallocation.
Provided Methods§
Sourcefn dealloc(&self, _handle: Self::Allocated<'_>) -> Result<(), Self::Error>
fn dealloc(&self, _handle: Self::Allocated<'_>) -> Result<(), Self::Error>
Release the region described by handle.
The default implementation is a no-op. Simple bump allocators accept this default; allocators with free-list tracking should override it.
After calling dealloc, handle must not be used for further I/O.
§Slice origin requirement
handle must have been returned directly by alloc
or by realloc on this same allocator instance.
Passing an arbitrary sub-slice obtained via BStackSlice::subslice,
BStackSlice::subslice_range, or a manually constructed
BStackSlice::new is not supported and may corrupt the allocator’s
internal state.
§Errors
The default never errors. Overriding implementations may return
Self::Error from underlying operations.
Sourcefn len(&self) -> Result<u64>
fn len(&self) -> Result<u64>
Return the current logical length of the backing stack payload.
Delegates to BStack::len.
Sourcefn is_empty(&self) -> Result<bool>
fn is_empty(&self) -> Result<bool>
Return true if the backing stack is empty.
Delegates to BStack::is_empty.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".
Implementors§
Source§impl BStackAllocator for CheckedSlabBStackAllocator
Available on crate feature set only.
impl BStackAllocator for CheckedSlabBStackAllocator
set only.type Error = Error
type Allocated<'a> = BStackSlice<'a, CheckedSlabBStackAllocator>
Source§impl BStackAllocator for FirstFitBStackAllocator
Available on crate feature set only.
impl BStackAllocator for FirstFitBStackAllocator
set only.type Error = Error
type Allocated<'a> = BStackSlice<'a, FirstFitBStackAllocator>
Source§impl BStackAllocator for GhostTreeBstackAllocator
impl BStackAllocator for GhostTreeBstackAllocator
type Error = Error
type Allocated<'a> = BStackSlice<'a, GhostTreeBstackAllocator>
Source§impl BStackAllocator for LinearBStackAllocator
impl BStackAllocator for LinearBStackAllocator
type Error = Error
type Allocated<'a> = BStackSlice<'a, LinearBStackAllocator>
Source§impl BStackAllocator for ManualAllocator
impl BStackAllocator for ManualAllocator
type Error = Error
type Allocated<'a> = BStackSlice<'a, ManualAllocator>
Source§impl BStackAllocator for SlabBStackAllocator
Available on crate feature set only.
impl BStackAllocator for SlabBStackAllocator
set only.type Error = Error
type Allocated<'a> = BStackSlice<'a, SlabBStackAllocator>
Source§impl<A> BStackAllocator for DebugCheckingAllocator<A>where
A: BStackAllocator<Error = Error>,
Method Atomic Notes
allocNo Inner alloc then tracking update are two separate steps
reallocNo Inner realloc then tracking swap are two separate steps
deallocNo Tracking validation then inner dealloc are two separate steps
impl<A> BStackAllocator for DebugCheckingAllocator<A>where
A: BStackAllocator<Error = Error>,
| Method | Atomic | Notes |
|---|---|---|
alloc | No | Inner alloc then tracking update are two separate steps |
realloc | No | Inner realloc then tracking swap are two separate steps |
dealloc | No | Tracking validation then inner dealloc are two separate steps |
A crash between the inner operation and the tracking update leaves the in-memory state inconsistent, but because tracking state is not persistent this only matters within a single process run.