(NOT A CONTRIBUTION)
I thought about async-unwinding more and I think this is the starting point:
I think the ideal API would be a
catch_unwind_async, which takes a future and returns a future combinator that also includes the states to unwind the future if it panics. Then instead of wrapping their polls in
catch_unwind, executors would wrap the futures they spawn in
catch_unwind_async and poll those to completion. When entering the poll method of this combinator, a thread local flag is set to trigger the async unwinding path when panics happen. (If catch_unwind is called inside of this scope, the flag is set back to normal).
The question is whether or not it's possible to create the future combinator which unwinds a future. I really have no knowledge in that domain.
I was the original proposer the
UnsafeFuture - back then called CompletionFuture in an RFC I wrote.
My take on this is that the
Future doesn't necessary has to contain the cancel method. A graceful cancellation request could be provided to any code via an orthogonal mechanism. I proposed a standardized CancellationToken mechanism for this:
If that token/signal is injected via some standardized mechanims (thread-local or task-local variable), anything in the future could react on it and gracefully run the future to the completed state. The Future could continue to just have a single
.poll method, and another bonus is that the standardized cancellation signal can be shared between synchronous and asynchronous contexts.
Overall I think there's at least 3 orthogonal aspects, which however are all closely related:
- Async drop (or just something like an
IAsyncDisposable as @scottmcm pointed out), plus potential extra tools to make it more likely to be called (
let async declarations,
async defer blocks, etc).
- Run to completion async fns - which would at least guarantee that code containing an
let async binding would indeed run the destructure, instead of being short-circuited by any
select! or synchronous drop in the call-stack.
- Graceful cancellation signals
I think that distinguishing syntactically between a completion future and a readiness future is an unnecessary burden that will probably cause a lot of trouble. I think having it be inferred like
Sync is probably the best choice.
poll_cancel would be basically optional, because it has a sound default implementation. Using a method is probably better than using a global for cancellation.