Skip to content

various#130

Merged
vinniefalco merged 3 commits intocppalliance:developfrom
vinniefalco:develop
Feb 4, 2026
Merged

various#130
vinniefalco merged 3 commits intocppalliance:developfrom
vinniefalco:develop

Conversation

@vinniefalco
Copy link
Member

@vinniefalco vinniefalco commented Feb 4, 2026

Summary by CodeRabbit

  • New Features

    • Executor type information can now be queried at runtime for improved type introspection.
  • Refactor

    • Enhanced resource cleanup and task completion signaling in asynchronous operations.
    • Type identification utilities now support compile-time constant expression evaluation.

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Added type-erasure metadata support to executor_ref via a type_id field in its vtable and public method. Refactored when_all completion signaling to occur after runner self-destruction in final_suspend, eliminating explicit destructor logic. Made type_id() function constexpr.

Changes

Cohort / File(s) Summary
Type Erasure Metadata
include/boost/capy/ex/executor_ref.hpp, include/boost/capy/detail/type_id.hpp
Added type_id member to executor_vtable initialized with type metadata. Exposed public type_id() method on executor_ref. Made type_id() function constexpr for constant expression evaluation.
Runner Lifecycle Refactoring
include/boost/capy/when_all.hpp
Removed destructor and signal_completion() helper from when_all_state. Refactored final_suspend awaiter to self-destruct runner handle before decrementing counter and dispatching continuation, using local state copies to ensure safe access after destruction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • The usual suspects #125: Modifies executor_ref vtable structure and API dispatch member/signature alongside this PR's type_id field and method additions.

Poem

🐰 ✨ A carrot's whisper through the code—
Type secrets now the executors hold,
When_all's runners bow politely, then self-destruct with grace,
No lingering ghosts in memory's place! 🌿

🚥 Pre-merge checks | ✅ 1 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The pull request title 'various' is vague and generic, providing no meaningful information about the actual changes made. Provide a descriptive title that clearly summarizes the main changes, such as 'Add type erasure support to executor_ref and optimize when_all completion handling' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
include/boost/capy/ex/executor_ref.hpp (1)

38-70: ⚠️ Potential issue | 🔴 Critical

Fix constexpr incompatibility with RTTI-enabled builds.

vtable_for is declared inline constexpr, but it initializes type_id with &detail::type_id<Ex>(). When BOOST_CAPY_NO_RTTI is false (RTTI enabled), type_id<Ex>() is not constexpr and returns the result of typeid(T), which is a runtime operation. This makes the constexpr initialization invalid and causes compilation failures in RTTI builds.

Add a conditional compilation guard or make vtable_for non-constexpr when RTTI is enabled:

Option 1: Conditional constexpr
`#if` BOOST_CAPY_NO_RTTI
template<class Ex>
inline constexpr executor_vtable vtable_for = { ... };
`#else`
template<class Ex>
inline executor_vtable vtable_for = { ... };
`#endif`
🧹 Nitpick comments (1)
include/boost/capy/when_all.hpp (1)

327-327: Remove or justify the redundant comment.
The Line 327 comment restates the immediately following launch logic without explaining rationale. Consider removing it or replacing it with a non-obvious “why” note.

Proposed cleanup
-        // Launch all tasks concurrently

As per coding guidelines: Single-line // comments within code should be used sparingly and judiciously, explaining the why (not the what or how) when it is non-obvious.

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 4, 2026

An automated preview of the documentation is available at https://130.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-02-04 03:49:18 UTC

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 4, 2026

GCOVR code coverage report https://130.capy.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://130.capy.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://130.capy.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-04 03:53:09 UTC

Runners now self-destruct in final_suspend before signaling completion.
This prevents the race where inline dispatch resumes the parent, destroys
when_all_state, and the state destructor tries to destroy still-executing
runner handles.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@include/boost/capy/when_all.hpp`:
- Around line 165-183: The await_suspend method calls caller_ex.dispatch(cont)
inside a noexcept function which can terminate if dispatch throws; fix by either
updating the executor contract to require Executor::dispatch be noexcept (adjust
the executor concept in concept/executor.hpp and document the requirement) or
make await_suspend exception-safe by wrapping the dispatch call in a try/catch
that captures any exception from caller_ex.dispatch(cont) and stores/handles it
via when_all_state (e.g., use caller_ex/caller_ex_.dispatch(cont) inside a try
block and on catch store the exception into state->caller_ex_ or
caller_ex.dispatch error path and ensure no exceptions escape await_suspend);
reference await_suspend, caller_ex, continuation_, and when_all_state to locate
the change.

Comment on lines +165 to +183
void await_suspend(coro h) noexcept
{
// Signal completion; last task resumes parent
return p_->state_->signal_completion();
// Extract everything needed for signaling before
// self-destruction. Inline dispatch may destroy
// when_all_state, so we can't access members after.
auto* state = p_->state_;
auto* counter = &state->remaining_count_;
auto caller_ex = state->caller_ex_;
auto cont = state->continuation_;

// Self-destruct first - state no longer destroys runners
h.destroy();

// Signal completion. If last, dispatch parent.
// Uses only local copies - safe even if state
// is destroyed during inline dispatch.
auto remaining = counter->fetch_sub(1, std::memory_order_acq_rel);
if(remaining == 1)
caller_ex.dispatch(cont);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect `coro` ownership semantics
echo "=== Searching for coro definition ==="
rg -n -C3 --type=cpp 'class\s+coro|struct\s+coro|using\s+coro' include/boost/capy/coro.hpp

# Inspect Executor concept requirements for dispatch noexcept
echo -e "\n=== Searching for dispatch in executor concept ==="
rg -n -C3 --type=cpp 'dispatch' include/boost/capy/concept/executor.hpp

Repository: cppalliance/capy

Length of output: 1691


🏁 Script executed:

#!/bin/bash
# Find when_all_state definition
echo "=== Searching for when_all_state definition ==="
rg -n 'struct\s+when_all_state|class\s+when_all_state' include/boost/capy/when_all.hpp

# Check for runner_handles_ member
echo -e "\n=== Searching for runner_handles_ ==="
rg -n 'runner_handles_' include/boost/capy/when_all.hpp

# Check the destructor and cleanup
echo -e "\n=== Searching for when_all_state destructor ==="
rg -n -A20 '~when_all_state' include/boost/capy/when_all.hpp

Repository: cppalliance/capy

Length of output: 320


🏁 Script executed:

#!/bin/bash
# Get the when_all_state struct definition
echo "=== when_all_state definition ==="
sed -n '78,150p' include/boost/capy/when_all.hpp

# Also check if there's any cleanup/destruction of handles elsewhere
echo -e "\n=== Checking for handle cleanup patterns ==="
rg -n 'destroy\(\)' include/boost/capy/when_all.hpp

Repository: cppalliance/capy

Length of output: 2343


🏁 Script executed:

#!/bin/bash
# Get full executor concept documentation
echo "=== Full Executor concept ==="
sed -n '30,100p' include/boost/capy/concept/executor.hpp

Repository: cppalliance/capy

Length of output: 2432


Verify that Executor::dispatch is non-throwing for noexcept await_suspend.

The Executor concept does not mark dispatch as noexcept (see the syntactic requirements in concept/executor.hpp), but await_suspend calls it in a noexcept context at line 176. If dispatch throws, the program will terminate. Confirm this is intentional or mark dispatch as noexcept in the executor contract.

(Note: The double-destruction concern is not valid—when_all_state explicitly documents that runners self-destruct in final_suspend and expects no destruction during state teardown.)

🤖 Prompt for AI Agents
In `@include/boost/capy/when_all.hpp` around lines 165 - 183, The await_suspend
method calls caller_ex.dispatch(cont) inside a noexcept function which can
terminate if dispatch throws; fix by either updating the executor contract to
require Executor::dispatch be noexcept (adjust the executor concept in
concept/executor.hpp and document the requirement) or make await_suspend
exception-safe by wrapping the dispatch call in a try/catch that captures any
exception from caller_ex.dispatch(cont) and stores/handles it via when_all_state
(e.g., use caller_ex/caller_ex_.dispatch(cont) inside a try block and on catch
store the exception into state->caller_ex_ or caller_ex.dispatch error path and
ensure no exceptions escape await_suspend); reference await_suspend, caller_ex,
continuation_, and when_all_state to locate the change.

@vinniefalco vinniefalco merged commit 6e236fd into cppalliance:develop Feb 4, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants