#[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 accommodate 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.
Implementations§
Source§impl<'a, T, const STACK_SIZE: usize> StackFuture<'a, T, STACK_SIZE>
impl<'a, T, const STACK_SIZE: usize> StackFuture<'a, T, STACK_SIZE>
Sourcepub fn from<F>(future: F) -> StackFuture<'a, T, STACK_SIZE> ⓘ
pub fn from<F>(future: F) -> StackFuture<'a, T, STACK_SIZE> ⓘ
Creates a StackFuture
from an existing future
See the documentation on StackFuture
for examples of how to use this.
The size and alignment requirements are statically checked, so it is a compiler error
to use this with a future that does not fit within the StackFuture
’s size and
alignment requirements.
The following example illustrates a compile error for a future that is too large.
// Fails because the future contains a large array and is therefore too big to fit in
// a 16-byte `StackFuture`.
let f = StackFuture::<_, { 16 }>::from(async {
let x = [0u8; 4096];
async {}.await;
println!("{}", x.len());
});
The example below illustrates a compiler error for a future whose alignment is too large.
#[derive(Debug)]
#[repr(align(256))]
struct BigAlignment(usize);
// Fails because the future contains a large array and is therefore too big to fit in
// a 16-byte `StackFuture`.
let f = StackFuture::<_, { 16 }>::from(async {
let x = BigAlignment(42);
async {}.await;
println!("{x:?}");
});
Sourcepub fn try_from<F>(
future: F,
) -> Result<StackFuture<'a, T, STACK_SIZE>, IntoStackFutureError<F>>
pub fn try_from<F>( future: F, ) -> Result<StackFuture<'a, T, STACK_SIZE>, IntoStackFutureError<F>>
Attempts to create a StackFuture
from an existing future
If the StackFuture
is not large enough to hold future
, this function returns an
Err
with the argument future
returned to you.
Panics
If we cannot satisfy the alignment requirements for F
, this function will panic.
Sourcepub fn from_or_box<F>(future: F) -> StackFuture<'a, T, STACK_SIZE> ⓘ
Available on crate feature alloc
only.
pub fn from_or_box<F>(future: F) -> StackFuture<'a, T, STACK_SIZE> ⓘ
alloc
only.Creates a StackFuture from the given future, boxing if necessary
This version will succeed even if the future is larger than STACK_SIZE
. If the future
is too large, from_or_box
will allocate a Box
on the heap and store the resulting
boxed future in the StackFuture
.
The same thing also happens if the wrapped future’s alignment is larger than StackFuture’s alignment.
This function requires the “alloc” crate feature.
Sourcepub const fn has_space_for<F>() -> bool
pub const fn has_space_for<F>() -> bool
Determines whether this StackFuture
can hold a value of type F
Sourcepub const fn has_space_for_val<F>(_: &F) -> bool
pub const fn has_space_for_val<F>(_: &F) -> bool
Determines whether this StackFuture
can hold the referenced value
Sourcepub const fn has_alignment_for<F>() -> bool
pub const fn has_alignment_for<F>() -> bool
Determines whether this StackFuture
’s alignment is compatible with the
type F
.
Sourcepub const fn has_alignment_for_val<F>(_: &F) -> bool
pub const fn has_alignment_for_val<F>(_: &F) -> bool
Determines whether this StackFuture
’s alignment is compatible with the
referenced value.
Trait Implementations§
Source§impl<'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>
Source§impl<'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> Freeze for StackFuture<'a, T, STACK_SIZE>
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§
Source§impl<F, T> AssetReaderFuture for F
impl<F, T> AssetReaderFuture for F
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<F> FutureExt for F
impl<F> FutureExt for F
Source§fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
fn catch_unwind(self) -> CatchUnwind<Self>where
Self: Sized + UnwindSafe,
std
only.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more