Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,18 @@ namespace hpx::execution::experimental::detail {
return {};
}
} // namespace hpx::execution::experimental::detail

namespace hpx::execution::experimental {

// Out-of-class definition for run_loop::env_t::query declared in
// run_loop.hpp. Defined here (not there) because the body needs the
// complete sync_wait_domain type. Templating on CPO defers instantiation
// so the trailing-return forward decl in run_loop.hpp is sufficient
// at declaration site.
template <typename CPO>
auto run_loop::env_t::query(get_completion_domain_t<CPO>) noexcept
-> detail::sync_wait_domain
{
return {};
}
} // namespace hpx::execution::experimental
28 changes: 13 additions & 15 deletions libs/core/execution/include/hpx/execution/algorithms/run_loop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,17 @@ namespace hpx::execution::experimental {
auto query(
get_completion_scheduler_t<set_stopped_t>) const noexcept;

//[[nodiscard]]
//static auto query(get_completion_domain_t<set_value_t>) noexcept;

//[[nodiscard]]
//static auto query(get_completion_domain_t<set_stopped_t>) noexcept;
// P3826R5: advertise the HPX-aware sync_wait domain on this
// env so that stdexec::sync_wait routes through
// detail::sync_wait_domain instead of default_domain. The body
// is defined in detail/sync_wait_domain.hpp after sync_wait_domain
// is complete; this header only forward-declares it (see top of
// file). Templating on CPO defers instantiation until the
// domain type is fully visible to the caller.
template <typename CPO>
[[nodiscard]]
static auto query(get_completion_domain_t<CPO>) noexcept
-> detail::sync_wait_domain;

run_loop* loop;
};
Expand Down Expand Up @@ -378,16 +384,8 @@ namespace hpx::execution::experimental {
return query(get_completion_scheduler<set_value_t>);
}

//auto run_loop::env_t::query(get_completion_domain_t<set_value_t>) noexcept
//{
// return hpx::execution::experimental::detail::sync_wait_domain{};
//}

//inline auto run_loop::env_t::query(
// get_completion_domain_t<set_stopped_t>) noexcept
//{
// return query(get_completion_domain<set_value_t>);
//}
// run_loop::env_t::query(get_completion_domain_t<CPO>) is defined in
// detail/sync_wait_domain.hpp once sync_wait_domain is complete.

///////////////////////////////////////////////////////////////////////////
HPX_CXX_CORE_EXPORT using run_loop_scheduler = run_loop::run_loop_scheduler;
Expand Down
81 changes: 81 additions & 0 deletions libs/core/execution/tests/unit/algorithm_run_loop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,86 @@ void test_completion_scheduler()
loop.run();
}

// Regression test for the run_loop -> sync_wait_domain integration:
// verify that the P3826R5 resolution chain
//
// sender env -> get_completion_scheduler<set_value_t>
// -> run_loop_scheduler
// -> get_completion_domain<set_value_t>
// -> detail::sync_wait_domain
//
// terminates at detail::sync_wait_domain. With this in place,
// stdexec::sync_wait on a run_loop-scheduled sender dispatches through
// HPX's cooperative apply_sender(sync_wait_t) instead of default_domain's
// OS-blocking wait. Checks are static_asserts so a regression fails the
// build rather than a runtime test.
void test_completion_domain()
{
using sync_wait_domain =
hpx::execution::experimental::detail::sync_wait_domain;

ex::run_loop loop;
[[maybe_unused]] auto sched = loop.get_scheduler();

// 1. Direct: the env returned by run_loop_sender.get_env() exposes
// get_completion_domain<set_value_t> -> sync_wait_domain.
{
auto sender = ex::schedule(sched);
auto env = ex::get_env(sender);
using domain_t =
std::decay_t<decltype(ex::get_completion_domain<ex::set_value_t>(
env))>;
static_assert(std::is_same_v<domain_t, sync_wait_domain>,
"run_loop env's get_completion_domain<set_value_t> should "
"resolve to detail::sync_wait_domain");
}

// 2. set_stopped_t resolves the same way (templated query covers all
// CPOs the env recognises).
{
auto sender = ex::schedule(sched);
auto env = ex::get_env(sender);
using domain_t =
std::decay_t<decltype(ex::get_completion_domain<ex::set_stopped_t>(
env))>;
static_assert(std::is_same_v<domain_t, sync_wait_domain>,
"run_loop env's get_completion_domain<set_stopped_t> should "
"resolve to detail::sync_wait_domain");
}

// 3. Full P3826R5 chain through the scheduler: from a sender's env,
// get_completion_scheduler<set_value_t> -> run_loop_scheduler,
// then on that scheduler get_completion_domain<set_value_t>
// -> sync_wait_domain. This is the path stdexec::sync_wait walks.
{
auto sender = ex::schedule(sched);
auto completion_scheduler =
ex::get_completion_scheduler<ex::set_value_t>(ex::get_env(sender));
using domain_t =
std::decay_t<decltype(ex::get_completion_domain<ex::set_value_t>(
completion_scheduler))>;
static_assert(std::is_same_v<domain_t, sync_wait_domain>,
"run_loop_scheduler's get_completion_domain<set_value_t> should "
"resolve to detail::sync_wait_domain");
}

// 4. Same chain on a composed sender (just | continues_on(sched)).
{
auto sender = ex::just(42) | ex::continues_on(sched);
auto completion_scheduler =
ex::get_completion_scheduler<ex::set_value_t>(ex::get_env(sender));
using domain_t =
std::decay_t<decltype(ex::get_completion_domain<ex::set_value_t>(
completion_scheduler))>;
static_assert(std::is_same_v<domain_t, sync_wait_domain>,
"composed-sender completion_scheduler should still resolve "
"get_completion_domain<set_value_t> to detail::sync_wait_domain");
}

loop.finish();
loop.run();
}

void do_run_test(void (*func)(), char const* func_name)
{
std::cout << func_name << "\n";
Expand Down Expand Up @@ -1867,6 +1947,7 @@ int hpx_main()
RUN_TEST(test_bulk);

RUN_TEST(test_completion_scheduler);
RUN_TEST(test_completion_domain);

return hpx::local::finalize();
}
Expand Down
Loading