#[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

Creates a StackFuture from an existing future

See the documentation on StackFuture for examples of how to use this.

Trait Implementations

Executes the destructor for this type. Read more

The type of value produced on completion.

Attempt to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The output that the future will produce on completion.

Which kind of future are we turning this into?

Creates a future from a value. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.