1 unstable release

0.1.0 Oct 15, 2024

#931 in Asynchronous


Used in ampsc

MIT/Apache

125KB
210 lines

continue

logo

continue is a Rust implementation of a Swift-style continuation API.

For those more familiar with Rust

A continuation is a type of single-use channel. The sender side of the channel sends a value. The receiver of the channel is a Future, that Outputs said value. (It is a programmer error to drop a sender before sending).

A common usecase for the continuation type is when you need to implement a custom Future based on being signaled by an external source when the Future is complete.

For those more familiar with Swift

continue is the answer to how to do withCheckedContinuation, CheckedContinuation, and related APIs when in Rust.

For those entirely too familiar with Rust

You may well ask: why use this? I can 'simply' write my output into the future's memory, signal the waker, and be done with it.

Not quite. First, because wakers implicitly have a short lifetime (until the next poll, e.g. you must re-register wakers on each poll), you need some way to smuggle this value across threads. The usual hammer for this nail is atomic-waker, which it will not surprise you to learn is a dependency.

Secondly Drop is surprisingly hard. In Rust, the Future side can be dropped early. In which case: a) are you writing to a sound memory location, b) will you Drop the right number of times, c) Did you want to run some code on Drop to cancel in-flight tasks, d) Did you want to optimistically poll the cancellation state and how will you smuggle it across, etc.

Thirdly, executors are surprisingly hard. It would be sound for an executor to keep polling you forever after it has a result, is your implementation sound in that case? Across Drop and !Clone types?

I found myself making too many mistakes, in too many places, and so I've decided to make them all in one place: right here!

Dependencies

~255–710KB
~16K SLoC