Skip to content

Conversation

@dietmarkuehl
Copy link
Member

No description provided.

Copilot AI review requested due to automatic review settings January 15, 2026 22:52
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements the affine_on sender adaptor, which ensures a sender completes on the same scheduler it was started on, even if the sender changes the scheduler. The scheduler is obtained from the receiver's environment using get_scheduler.

Changes:

  • Adds new affine_on sender adaptor with customization point support for nested senders
  • Updates run_loop to use environment-dependent completion signatures based on stop token availability
  • Fixes tutorial example to remove unnecessary dereference operator

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
include/beman/execution/detail/affine_on.hpp New sender adaptor implementation with scheduler affinity
include/beman/execution/detail/sender_has_affine_on.hpp Concept to check if sender supports affine_on customization
include/beman/execution/detail/nested_sender_has_affine_on.hpp Concept to check if nested sender supports affine_on
include/beman/execution/detail/just.hpp Adds affine_on customization returning sender unchanged
include/beman/execution/detail/read_env.hpp Adds affine_on customization returning sender unchanged
include/beman/execution/detail/then.hpp Adds affine_on customization for nested sender forwarding
include/beman/execution/detail/write_env.hpp Adds affine_on customization for nested sender forwarding
include/beman/execution/detail/run_loop.hpp Updates completion signatures to be environment-dependent
include/beman/execution/detail/let.hpp Adds noexcept specification and conditional error handling
include/beman/execution/execution.hpp Includes affine_on header
tests/beman/execution/exec-affine-on.test.cpp Comprehensive test suite for affine_on
tests/beman/execution/exec-run-loop-types.test.cpp Updates tests for new completion signature behavior
src/beman/execution/CMakeLists.txt Adds new headers to build
tests/beman/execution/CMakeLists.txt Adds new test to build
docs/overview.md Documents affine_on and write_env adaptors
docs/tutorial.mds Fixes sync_wait usage example

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

#define INCLUDED_INCLUDE_BEMAN_EXECUTION_DETAIL_AFFINE_ON

#include <beman/execution/detail/env.hpp>
#include <beman/execution/detail/env.hpp>
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Duplicate include directive for env.hpp. Remove the duplicate include on line 8.

Suggested change
#include <beman/execution/detail/env.hpp>

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +110
#if 0
if constexpr (requires(const child_tag_t& t) {
{
t.affine_on(::beman::execution::detail::forward_like<Sender>(child), env)
} -> ::beman::execution::sender;
})
#else
if constexpr (::beman::execution::detail::nested_sender_has_affine_on<Sender, Env>)
#endif
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Commented-out code should be removed. If the alternative implementation using #if 0 is no longer needed, remove lines 102-108 and 110 entirely, keeping only the active implementation.

Suggested change
#if 0
if constexpr (requires(const child_tag_t& t) {
{
t.affine_on(::beman::execution::detail::forward_like<Sender>(child), env)
} -> ::beman::execution::sender;
})
#else
if constexpr (::beman::execution::detail::nested_sender_has_affine_on<Sender, Env>)
#endif
if constexpr (::beman::execution::detail::nested_sender_has_affine_on<Sender, Env>)

Copilot uses AI. Check for mistakes.

#include <beman/execution/detail/affine_on.hpp>
#include <beman/execution/detail/connect.hpp>
#include <beman/execution/detail/env.hpp>
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Duplicate include directive for env.hpp. Remove the duplicate include on line 17.

Copilot uses AI. Check for mistakes.
#include <beman/execution/detail/sender_in.hpp>
#include <beman/execution/detail/starts_on.hpp>
#include <beman/execution/detail/sync_wait.hpp>
#include <beman/execution/detail/env.hpp>
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Duplicate include directive for env.hpp. Remove the duplicate include on line 17.

Suggested change
#include <beman/execution/detail/env.hpp>

Copilot uses AI. Check for mistakes.
#include <beman/execution/detail/just.hpp>
#include <beman/execution/detail/read_env.hpp>
#include <beman/execution/detail/write_env.hpp>
#include <beman/execution/detail/prop.hpp>
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Duplicate include directive for prop.hpp. Remove the duplicate include on line 18.

Copilot uses AI. Check for mistakes.
#include <beman/execution/detail/starts_on.hpp>
#include <beman/execution/detail/sync_wait.hpp>
#include <beman/execution/detail/env.hpp>
#include <beman/execution/detail/prop.hpp>
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Duplicate include directive for prop.hpp. Remove the duplicate include on line 18.

Suggested change
#include <beman/execution/detail/prop.hpp>

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +55
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The expression this->awaiter_&& this->awaiter_->complete() uses the logical AND operator (&&) instead of the short-circuit evaluation operator. This should likely be this->awaiter_ && this->awaiter_->complete() with proper conditional evaluation, or use an if statement: if (this->awaiter_) this->awaiter_->complete();

Suggested change
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_value(auto&&...) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_error(auto&&) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_stopped() && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +55
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The expression this->awaiter_&& this->awaiter_->complete() uses the logical AND operator (&&) instead of the short-circuit evaluation operator. This should likely be this->awaiter_ && this->awaiter_->complete() with proper conditional evaluation, or use an if statement: if (this->awaiter_) this->awaiter_->complete();

Suggested change
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_value(auto&&...) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_error(auto&&) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_stopped() && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +53 to +55
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

The expression this->awaiter_&& this->awaiter_->complete() uses the logical AND operator (&&) instead of the short-circuit evaluation operator. This should likely be this->awaiter_ && this->awaiter_->complete() with proper conditional evaluation, or use an if statement: if (this->awaiter_) this->awaiter_->complete();

Suggested change
auto set_value(auto&&...) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_error(auto&&) && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_stopped() && noexcept -> void { this->awaiter_&& this->awaiter_->complete(); }
auto set_value(auto&&...) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_error(auto&&) && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}
auto set_stopped() && noexcept -> void {
if (this->awaiter_) {
this->awaiter_->complete();
}
}

Copilot uses AI. Check for mistakes.
docs/overview.md Outdated
<details>
<summary><code>affine_on(<i>sender</i>) -> <i>sender-of</i><<i>completions-of</i>(<i>sender</i>)></code></summary>
The expression <code>affine_on(<i>sender</i>)</code> creates
a sender which completes on the same scheduler it was started on, even if <code><i>sender</i></code> changes the scheduler. The scheduler to resume on is determined using <code>get_scheduler(get_env(<i>rcvr</i>))</code> where <code><i>rcvr</i></code> is the reciver the sender is <code>connect</code>ed to.
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

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

Corrected spelling of 'reciver' to 'receiver'.

Suggested change
a sender which completes on the same scheduler it was started on, even if <code><i>sender</i></code> changes the scheduler. The scheduler to resume on is determined using <code>get_scheduler(get_env(<i>rcvr</i>))</code> where <code><i>rcvr</i></code> is the reciver the sender is <code>connect</code>ed to.
a sender which completes on the same scheduler it was started on, even if <code><i>sender</i></code> changes the scheduler. The scheduler to resume on is determined using <code>get_scheduler(get_env(<i>rcvr</i>))</code> where <code><i>rcvr</i></code> is the receiver the sender is <code>connect</code>ed to.

Copilot uses AI. Check for mistakes.
@coveralls
Copy link

coveralls commented Jan 15, 2026

Coverage Status

coverage: 92.636% (+0.6%) from 92.054%
when pulling 475fc41 on affine_on
into 562ec1d on main.

@dietmarkuehl dietmarkuehl merged commit 7d2a2b0 into main Jan 15, 2026
37 checks passed
@dietmarkuehl dietmarkuehl deleted the affine_on branch January 15, 2026 23:23
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.

3 participants