pub struct ScopedCoroutine<'a, Input, Yield, Return, Stack: Stack> { /* private fields */ }
Expand description

A coroutine wraps a closure and allows suspending its execution more than once, returning a value each time.

Lifetime

The 'a lifetime here refers to the lifetime of the initial function in a coroutine and ensures that the coroutine doesn’t exceed the lifetime of the initial function.

Dropping a coroutine

When a coroutine is dropped, its stack must be unwound so that all object on it are properly dropped. This is done by calling force_unwind to unwind the stack. If force_unwind fails then the program is aborted.

See the Coroutine::force_unwind function for more details.

Send

In the general case, a coroutine can only be sent to another if all of the data on its stack is Send. There is no way to guarantee this using Rust language features so Coroutine does not implement the Send trait.

However if all of the code executed by a coroutine is under your control and you can ensure that all types on the stack when a coroutine is suspended are Send then it is safe to manually implement Send for a coroutine.

Implementations§

source§

impl<'a, Input, Yield, Return> ScopedCoroutine<'a, Input, Yield, Return, DefaultStack>

source

pub fn new<F>(f: F) -> Selfwhere F: FnOnce(&Yielder<Input, Yield>, Input) -> Return + 'a,

Creates a new coroutine which will execute func on a new stack.

This function returns a Coroutine which, when resumed, will execute func to completion. When desired the func can suspend itself via Yielder::suspend.

source§

impl<'a, Input, Yield, Return, Stack: Stack> ScopedCoroutine<'a, Input, Yield, Return, Stack>

source

pub fn with_stack<F>(stack: Stack, f: F) -> Selfwhere F: FnOnce(&Yielder<Input, Yield>, Input) -> Return + 'a,

Creates a new coroutine which will execute func on the given stack.

This function returns a coroutine which, when resumed, will execute func to completion. When desired the func can suspend itself via Yielder::suspend.

source

pub fn resume(&mut self, val: Input) -> CoroutineResult<Yield, Return>

Resumes execution of this coroutine.

This function will transfer execution to the coroutine and resume from where it last left off.

If the coroutine calls Yielder::suspend then this function returns CoroutineResult::Yield with the value passed to suspend.

If the coroutine returns then this function returns CoroutineResult::Return with the return value of the coroutine.

Panics

Panics if the coroutine has already finished executing.

If the coroutine itself panics during execution then the panic will be propagated to this caller.

source

pub fn started(&self) -> bool

Returns whether this coroutine has been resumed at least once.

source

pub fn done(&self) -> bool

Returns whether this coroutine has finished executing.

A coroutine that has returned from its initial function can no longer be resumed.

source

pub unsafe fn force_reset(&mut self)

Forcibly marks the coroutine as having completed, even if it is currently suspended in the middle of a function.

Safety

This is equivalent to a longjmp all the way back to the initial function of the coroutine, so the same rules apply.

This can only be done safely if there are no objects currently on the coroutine’s stack that need to execute Drop code.

source

pub fn force_unwind(&mut self)

Unwinds the coroutine stack, dropping any live objects that are currently on the stack. This is automatically called when the coroutine is dropped.

If the coroutine has already completed then this function is a no-op.

If the coroutine is currently suspended on a Yielder::suspend call then unwinding it requires the unwind feature to be enabled and for the crate to be compiled with -C panic=unwind.

Panics

This function panics if the coroutine could not be fully unwound. This can happen for one of two reasons:

  • The ForcedUnwind panic that is used internally was caught and not rethrown.
  • This crate was compiled without the unwind feature and the coroutine is currently suspended in the yielder (started && !done).
source

pub fn into_stack(self) -> Stack

Extracts the stack from a coroutine that has finished executing.

This allows the stack to be re-used for another coroutine.

source

pub fn trap_handler(&self) -> CoroutineTrapHandler<Return>

Returns a CoroutineTrapHandler which can be used to handle traps that occur inside the coroutine. Examples of traps that can be handled are invalid memory accesses and stack overflows.

The returned CoroutineTrapHandler can be used in a trap handler to force the trapping coroutine to return with a specific value, after which is it considered to have completed and can no longer be resumed.

Needless to say, this is extremely unsafe and must be used with extreme care. See CoroutineTrapHandler::setup_trap_handler for the exact safety requirements.

Trait Implementations§

source§

impl<'a, Input, Yield, Return, Stack: Stack> Drop for ScopedCoroutine<'a, Input, Yield, Return, Stack>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<Input, Yield, Return, Stack: Stack + Sync> Sync for ScopedCoroutine<'_, Input, Yield, Return, Stack>

Auto Trait Implementations§

§

impl<'a, Input, Yield, Return, Stack> RefUnwindSafe for ScopedCoroutine<'a, Input, Yield, Return, Stack>where Stack: RefUnwindSafe,

§

impl<'a, Input, Yield, Return, Stack> !Send for ScopedCoroutine<'a, Input, Yield, Return, Stack>

§

impl<'a, Input, Yield, Return, Stack> Unpin for ScopedCoroutine<'a, Input, Yield, Return, Stack>where Stack: Unpin,

§

impl<'a, Input, Yield, Return, Stack> UnwindSafe for ScopedCoroutine<'a, Input, Yield, Return, Stack>where Stack: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

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

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.