-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Corral's currently advertised approach to asynchronous cancellation: AsyncFile f = co_await AsyncFile::open("..."); co_await anyOf( [&]() -> Task<> { /* do stuff with f */ }, untilCancelledAnd(f.close())); -- has a downside: upon cancellation from the outside, both children of `anyOf()` get cancelled simultaneously, which may bring problems if the body of "do stuff" clause features asynchronous cancellation and requires the file to remain in scope until its own cancellation completes. The naïve way of fixing this: Event done; co_await anyOf([&]() -> Task<> { ScopeGuard guard([&done]{ done.trigger(); }; // do stuff with f }, untilCancelledAnd([&]() -> Task<> { co_await done; co_await f.close(); }); — will deadlock, since anyOf() will require both children to fully cancel before it can resume and the parent can proceed with the destruction of `anyOf` awaitable — which will trigger the destruction of children and running the scope guard. We therefore need another combiner which would resemble the try/finally semantics more closely. This diff adds `corral::detail::TryFinally`, which has a few important differences from `anyOf(a, untilCancelledAnd(b))`: * it sequences cancellation of its children: when cancelled from the outside it cancels its try-block coroutine and waits until its cancellation completes before starting the finally-block coroutine; * it also fully destroys the try-block, including any local variables and lambda captures, thereby giving any synchronous scope guard a chance to trigger, before starting the finally-block. Similarly to `CORRAL_WITH_NURSERY()` macro, we can creatively (ab)use `co_yield` and macros to allow more user-friendly syntax: AsyncFile f = co_await AsyncFile::open("..."); CORRAL_TRY { // work with file } CORRAL_FINALLY { co_await f.close(); }; Similarly to C++ destructors, a finally-block is allowed to throw an exception, but not if there is already an exception in flight.
- Loading branch information
1 parent
bbb81f0
commit 8983280
Showing
9 changed files
with
385 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.