Conversation
Operation stacking is when you load a context with multiple coroutines. Before, this resulted in a memory leak, due to the active_handle being overwritten and lost. This also results in lifetime violation if the context stack, prior to the new coroutine being loaded, had objects with lifetimes that need to be destroyed. This change enables operation stacking so it is no longer erroneous behavior. Now the last coroutine loaded is the first one to be executed (LIFO) and up the chain until the first loaded coroutine is reached. \## Summary - Enables multiple coroutines to be loaded onto the same `context` in LIFO order — the last routine pushed runs first, allowing natural "stacking" of async work on a single context - Bans co-awaiting an l-value `future` (deleted `operator co_await() &`) to prevent accidentally awaiting a future from a different context; co-awaiting a future whose context was allocated inside a coroutine frame is now a contract violation (`contract_assert`) or `std::terminate` - Removes `[[clang::lifetimebound]]` from `awaiter` constructor - Simplify `await_suspend` to just return the stored handle and drop the explicit continuation chain. Continuation is now captured at `get_return_object()` time via `m_context->active_handle()` to enable operation stacking. \## Test plan - [x] `tests/async_stacking.test.cpp` — LIFO ordering with two and three routines on the same context - [x] `tests/context_swapping.test.cpp` — verifies that co-awaiting a future from a mismatched nested context triggers `std::terminate` (or contract violation when contracts are enabled) - [x] Existing `tests/basics.test.cpp` continues to pass with the updated `await_ready` logic
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Operation stacking is when you load a context with multiple coroutines. Before, this resulted in a memory leak, due to the active_handle being overwritten and lost. This also results in lifetime violation if the context stack, prior to the new coroutine being loaded, had objects with lifetimes that need to be destroyed. This change enables operation stacking so it is no longer erroneous behavior. Now the last coroutine loaded is the first one to be executed (LIFO) and up the chain until the first loaded coroutine is reached.
Summary
contextin LIFO order — the last routine pushed runs first, allowing natural "stacking" of async work on a single contextfuture(deletedoperator co_await() &) to prevent accidentally awaiting a future from a different context; co-awaiting a future whose context was allocated inside a coroutine frame is now a contract violation (contract_assert) orstd::terminate[[clang::lifetimebound]]fromawaiterconstructorawait_suspendto just return the stored handle and drop the explicit continuation chain. Continuation is now captured atget_return_object()time viam_context->active_handle()to enable operation stacking.void*for the offending future or context.Test plan
tests/async_stacking.test.cpp— LIFO ordering with two and three routines on the same contexttests/context_swapping.test.cpp— verifies that co-awaiting a future from a mismatched nested context triggersstd::terminate(or contract violation when contracts are enabled)tests/basics.test.cppcontinues to pass with the updatedawait_readylogicconan create .