Struct static_alloc::leaked::LeakBox
source · pub struct LeakBox<'ctx, T: ?Sized> { /* private fields */ }
Expand description
Represents an allocation within a Bump.
This is an owning pointer comparable to Box
. It drops the contained value when it is dropped
itself. The difference is that no deallocation logic is ever executed.
FIXME(non-breaking): the name is rather confusing. Maybe it should be BumpBox
or RefBox
?
Not StackBox
because the value’s location in memory is not the defining feature.
§Usage
This box can be used to manage one valid instance constructed within the memory provided by a
MaybeUninit
instance.
use core::mem::MaybeUninit;
use static_alloc::leaked::LeakBox;
let mut storage = MaybeUninit::uninit();
let leak_box = LeakBox::from(&mut storage);
// The string itself is not managed by `static_alloc`.
let mut instance = LeakBox::write(leak_box, String::new());
instance.push_str("Hello world!");
This box is the result of allocating from one of the Bump
allocators using its explicit API.
Being a box-like type, an Option
has the same size.
use core::mem::size_of;
use static_alloc::leaked::LeakBox;
type Boxed = LeakBox<'static, usize>;
type Optional = Option<Boxed>;
assert_eq!(size_of::<Boxed>(), size_of::<Optional>());
TODO: On nightly the inner type should be unsizable.
Implementations§
source§impl<'ctx, T: ?Sized> LeakBox<'ctx, T>
impl<'ctx, T: ?Sized> LeakBox<'ctx, T>
sourcepub fn into_raw(this: Self) -> *mut T
pub fn into_raw(this: Self) -> *mut T
Retrieve the raw pointer wrapped by this box.
After this method the caller is responsible for managing the value in the place behind the pointer. It will need to be dropped manually.
§Usage
You might manually drop the contained instance at a later point.
use static_alloc::{Bump, leaked::LeakBox};
let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let ptr = LeakBox::into_raw(leak_box);
unsafe {
core::ptr::drop_in_place(ptr);
}
An alternative is to later re-wrap the pointer
use static_alloc::{Bump, leaked::LeakBox};
let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let ptr = LeakBox::into_raw(leak_box);
unsafe {
let _ = LeakBox::from_raw(ptr);
};
sourcepub unsafe fn from_raw(pointer: *mut T) -> Self
pub unsafe fn from_raw(pointer: *mut T) -> Self
Wrap a raw pointer.
The most immediate use is to rewrap a pointer returned from into_raw
.
§Safety
The pointer must point to a valid instance of T
that is not aliased by any other
reference for the lifetime 'ctx
. In particular it must be valid aligned and initialized.
Dropping this LeakBox
will drop the instance, which the caller must also guarantee to be
sound.
sourcepub unsafe fn from_mut_unchecked(val: &'ctx mut T) -> Self
pub unsafe fn from_mut_unchecked(val: &'ctx mut T) -> Self
Wrap a mutable reference to a complex value as if it were owned.
§Safety
The value must be owned by the caller. That is, the mutable reference must not be used
after the LeakBox
is dropped. In particular the value must not be dropped by the caller.
§Example
use core::mem::ManuallyDrop;
use static_alloc::leaked::LeakBox;
fn with_stack_drop<T>(val: T) {
let mut val = ManuallyDrop::new(val);
// Safety:
// - Shadows the variable, rendering the prior inaccessible.
// - Dropping is now the responsibility of `LeakBox`.
let val = unsafe { LeakBox::from_mut_unchecked(&mut *val) };
}
// Demonstrate that it is correctly dropped.
let variable = core::cell::RefCell::new(0);
with_stack_drop(variable.borrow_mut());
assert!(variable.try_borrow_mut().is_ok());
sourcepub fn leak<'a>(this: Self) -> &'a mut Twhere
'ctx: 'a,
pub fn leak<'a>(this: Self) -> &'a mut Twhere
'ctx: 'a,
Leak the instances as a mutable reference.
After calling this method the value is no longer managed by LeakBox
. Its Drop impl will
not be automatically called.
§Usage
use static_alloc::{Bump, leaked::LeakBox};
let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let st: &mut String = LeakBox::leak(leak_box);
You can’t leak past the lifetime of the allocator.
let bump: Bump<[usize; 128]> = Bump::uninit();
let leak_box = bump.leak_box(String::from("Hello"))?;
let st: &mut String = LeakBox::leak(leak_box);
drop(bump);
// error[E0505]: cannot move out of `bump` because it is borrowed
st.to_lowercase();
//-- borrow later used here
source§impl<T: 'static> LeakBox<'static, T>
impl<T: 'static> LeakBox<'static, T>
sourcepub fn into_pin(this: Self) -> Pin<Self>
pub fn into_pin(this: Self) -> Pin<Self>
Pin an instance that’s leaked for the remaining program runtime.
After calling this method the value can only safely be referenced mutably if it is Unpin
,
otherwise it is only accessible behind a Pin
. Note that this does not imply that the
Drop
glue, or explicit Drop
-impl, is guaranteed to run.
§Usage
A decent portion of futures must be pinned before the can be awaited inside another
future. In particular this is required for self-referential futures that store pointers
into their own object’s memory. This is the case for the future type of an asnyc fn
if
there are potentially any stack references when it is suspended/waiting on another future.
Consider this example:
use static_alloc::{Bump, leaked::LeakBox};
async fn example(x: usize) -> usize {
// Holding reference across yield point.
// This requires pinning to run this future.
let y = &x;
core::future::ready(()).await;
*y
}
static POOL: Bump<[usize; 128]> = Bump::uninit();
let mut future = POOL.leak_box(example(0))
.expect("Enough space for small async fn");
let usage = async move {
// error[E0277]: `GenFuture<[static generator@src/leaked.rs …]>` cannot be unpinned
let _ = (&mut *future).await;
};
This method can be used to pin instances allocated from a global pool without requiring the
use of a macro or unsafe on the caller’s part. Now, with the correct usage of into_pin
:
use static_alloc::{Bump, leaked::LeakBox};
async fn example(x: usize) -> usize {
// Holding reference across yield point.
// This requires pinning to run this future.
let y = &x;
core::future::ready(()).await;
*y
}
static POOL: Bump<[usize; 128]> = Bump::uninit();
let future = POOL.leak_box(example(0))
.expect("Enough space for small async fn");
// PIN this future!
let mut future = LeakBox::into_pin(future);
let usage = async move {
let _ = future.as_mut().await;
};
source§impl<'ctx, T> LeakBox<'ctx, T>
impl<'ctx, T> LeakBox<'ctx, T>
sourcepub fn take(this: Self) -> T
pub fn take(this: Self) -> T
Remove the value, forgetting the box in the process.
This is similar to dereferencing a box (*leak_box
) but no deallocation is involved. This
becomes useful when the allocator turns out to have too short of a lifetime.
§Usage
You may want to move a long-lived value out of the current scope where it’s been allocated.
use static_alloc::{Bump, leaked::LeakBox};
let cell = RefCell::new(0usize);
let guard = {
let bump: Bump<[usize; 128]> = Bump::uninit();
let mut leaked = bump.leak_box(cell.borrow_mut()).unwrap();
**leaked = 1usize;
// Take the value, allowing use independent of the lifetime of bump
LeakBox::take(leaked)
};
assert!(cell.try_borrow().is_err());
drop(guard);
assert!(cell.try_borrow().is_ok());
sourcepub fn from_mut(val: &'ctx mut T) -> Selfwhere
T: Copy,
pub fn from_mut(val: &'ctx mut T) -> Selfwhere
T: Copy,
Wrap a mutable reference to a trivial value as if it were a box.
This is safe because such values can not have any Drop code and can be duplicated at will.
The usefulness of this operation is questionable but the author would be delighted to hear about any actual use case.
source§impl<'ctx, T> LeakBox<'ctx, MaybeUninit<T>>
impl<'ctx, T> LeakBox<'ctx, MaybeUninit<T>>
sourcepub fn write(this: Self, val: T) -> LeakBox<'ctx, T>
pub fn write(this: Self, val: T) -> LeakBox<'ctx, T>
Write a value into this box, initializing it.
This can be used to delay the computation of a value until after an allocation succeeded while maintaining all types necessary for a safe initialization.
§Usage
use static_alloc::{Bump, leaked::LeakBox};
let bump: Bump<[usize; 128]> = Bump::uninit();
let memory = bump.leak_box(MaybeUninit::uninit())?;
let value = LeakBox::write(memory, some_expensive_operation());
sourcepub unsafe fn assume_init(this: Self) -> LeakBox<'ctx, T>
pub unsafe fn assume_init(this: Self) -> LeakBox<'ctx, T>
Converts to LeakBox<T>
.
§Safety
The value must have been initialized as required by MaybeUninit::assume_init
. Calling
this when the content is not yet fully initialized causes immediate undefined behavior.
Trait Implementations§
source§impl<'ctx, T> From<&'ctx mut [MaybeUninit<T>]> for LeakBox<'ctx, [MaybeUninit<T>]>
impl<'ctx, T> From<&'ctx mut [MaybeUninit<T>]> for LeakBox<'ctx, [MaybeUninit<T>]>
Construct a LeakBox to an existing slice of MaybeUninit.
source§fn from(uninit: &'ctx mut [MaybeUninit<T>]) -> Self
fn from(uninit: &'ctx mut [MaybeUninit<T>]) -> Self
source§impl<'ctx, T> From<&'ctx mut MaybeUninit<T>> for LeakBox<'ctx, MaybeUninit<T>>
impl<'ctx, T> From<&'ctx mut MaybeUninit<T>> for LeakBox<'ctx, MaybeUninit<T>>
Construct a LeakBox to an existing MaybeUninit.
The MaybeUninit type is special in that we can treat any unique reference to an owned value as an owned value itself since it has no representational invariants.