Struct stackfuture::StackFuture
source · [−]#[repr(C)]pub struct StackFuture<'a, T, const STACK_SIZE: usize> { /* private fields */ }Expand description
A wrapper that stores a future in space allocated by the container
Often this space comes from the calling function’s stack, but it could just as well come from some other allocation.
A StackFuture can be used to emulate async functions in dyn Trait objects.
For example:
trait PseudoAsyncTrait {
fn do_something(&self) -> StackFuture<'_, (), { 512 }>;
}
impl PseudoAsyncTrait for i32 {
fn do_something(&self) -> StackFuture<'_, (), { 512 }> {
StackFuture::from(async {
// function body goes here
})
}
}
async fn use_dyn_async_trait(x: &dyn PseudoAsyncTrait) {
x.do_something().await;
}
async fn call_with_dyn_async_trait() {
use_dyn_async_trait(&42).await;
}This example defines PseudoAsyncTrait with a single method do_something.
The do_something method can be called as if it were declared as
async fn do_something(&self). To implement do_something, the easiest thing
to do is to wrap the body of the function in StackFuture::from(async { ... }),
which creates an anonymous future for the body and stores it in a StackFuture.
Because StackFuture does not know the size of the future it wraps, the maximum
size of the future must be specified in the STACK_SIZE parameter. In the example
here, we’ve used a stack size of 512, which is probably much larger than necessary
but would accomodate many futures besides the simple one we’ve shown here.
StackFuture ensures when wrapping a future that enough space is available, and
it also respects any alignment requirements for the wrapped future. Note that the
wrapped future’s alignment must be less than or equal to that of the overall
StackFuture struct.
The following example would panic because the future is too large:
fn large_stack_future() -> StackFuture<'static, u8, { 4 }> {
StackFuture::from(async {
let mut buf = [0u8; 256];
fill_buf(&mut buf).await;
buf[0]
})
}
async fn fill_buf(buf: &mut [u8]) {
buf[0] = 42;
}
let future = large_stack_future();The following example would panic because the alignment requirements can’t be met:
#[repr(align(4096))]
struct LargeAlignment(i32);
fn large_alignment_future() -> StackFuture<'static, i32, { 8192 }> {
StackFuture::from(async {
let mut buf = LargeAlignment(0);
fill_buf(&mut buf).await;
buf.0
})
}
async fn fill_buf(buf: &mut LargeAlignment) {
buf.0 = 42;
}
let future = large_alignment_future();Implementations
Trait Implementations
sourceimpl<'a, T, const STACK_SIZE: usize> Drop for StackFuture<'a, T, { STACK_SIZE }>
impl<'a, T, const STACK_SIZE: usize> Drop for StackFuture<'a, T, { STACK_SIZE }>
sourceimpl<'a, T, const STACK_SIZE: usize> Future for StackFuture<'a, T, { STACK_SIZE }>
impl<'a, T, const STACK_SIZE: usize> Future for StackFuture<'a, T, { STACK_SIZE }>
Auto Trait Implementations
impl<'a, T, const STACK_SIZE: usize> !RefUnwindSafe for StackFuture<'a, T, STACK_SIZE>
impl<'a, T, const STACK_SIZE: usize> Send for StackFuture<'a, T, STACK_SIZE>
impl<'a, T, const STACK_SIZE: usize> !Sync for StackFuture<'a, T, STACK_SIZE>
impl<'a, T, const STACK_SIZE: usize> !Unpin for StackFuture<'a, T, STACK_SIZE>
impl<'a, T, const STACK_SIZE: usize> !UnwindSafe for StackFuture<'a, T, STACK_SIZE>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
sourceimpl<F> IntoFuture for F where
F: Future,
impl<F> IntoFuture for F where
F: Future,
type IntoFuture = F
type IntoFuture = F
Which kind of future are we turning this into?
sourcefn into_future(self) -> <F as IntoFuture>::IntoFuture
fn into_future(self) -> <F as IntoFuture>::IntoFuture
Creates a future from a value. Read more