Skip to content

Feat/fork join executor p2300 bridge#7260

Open
shivansh023023 wants to merge 3 commits intoTheHPXProject:masterfrom
shivansh023023:feat/fork-join-executor-p2300-bridge
Open

Feat/fork join executor p2300 bridge#7260
shivansh023023 wants to merge 3 commits intoTheHPXProject:masterfrom
shivansh023023:feat/fork-join-executor-p2300-bridge

Conversation

@shivansh023023
Copy link
Copy Markdown
Contributor

executors: Add P2300 get_scheduler bridge for fork_join_executor

Fixes #5219 (partial)

Proposed Changes

  • Added free tag_invoke(get_scheduler_t, fork_join_executor const&)
    outside the class body, returning
    executor_scheduler<fork_join_executor>, so that the return type is
    fully defined at point of use
  • Replaced executor_scheduler_fwd.hpp include with the full
    executor_scheduler.hpp to ensure type completeness
  • Added tag_invoke(post_t, fork_join_executor const&) delegating to
    async_invoke so the generic executor_scheduler operation state
    can dispatch work onto the fork_join thread pool
  • Extended fork_join_executor unit tests with test_get_scheduler()
    verifying scheduler acquisition, work dispatch, and thread identity

Background

fork_join_executor is one of HPX's primary performance executors used
for NUMA-aware work-stealing. Without a get_scheduler bridge it cannot
participate in P2300 pipelines using continues_on, transfer, or
let_value. After this PR:

hpx::execution::experimental::fork_join_executor exec{};
auto sched = hpx::execution::experimental::get_scheduler(exec);
stdexec::sync_wait(
    stdexec::then(stdexec::schedule(sched), []{ return 42; }));

This follows the pattern established for sequenced_executor (#7238)
and parallel_executor (#7239).

Checklist

  • I have added a new feature and have added tests to go along with it.

Hackathon User added 2 commits May 9, 2026 12:16
Add executor_scheduler infrastructure (executor_scheduler,
executor_sender, executor_operation_state) that wraps any HPX
executor as a P2300 scheduler. This enables executors to participate
in sender/receiver pipelines via stdexec::schedule().

Add a get_scheduler tag_invoke overload to fork_join_executor that
returns an executor_scheduler<fork_join_executor>. This allows:

  fork_join_executor exec{};
  auto sched = get_scheduler(exec);
  sync_wait(then(schedule(sched), []{ return 42; }));

The tag_invoke uses a default template parameter with a requires
clause to defer instantiation of the incomplete executor_scheduler
return type, following the established pattern from the parallel
and sequenced executor bridges.

New files:
- executor_scheduler.hpp: Full scheduler/sender/operation_state impl
- fwd/executor_scheduler_fwd.hpp: Forward declarations only

Modified files:
- fork_join_executor.hpp: Add fwd include + get_scheduler friend
- fork_join_executor.cpp: Add test_get_scheduler() with 3 subtests
- CMakeLists.txt: Register new headers
@shivansh023023 shivansh023023 requested a review from hkaiser as a code owner May 9, 2026 08:10
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 9, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@StellarBot
Copy link
Copy Markdown
Collaborator

Can one of the admins verify this patch?

@hkaiser hkaiser added type: enhancement type: compatibility issue category: senders/receivers Implementations of the p0443r14 / p2300 + p1897 proposals labels May 9, 2026
Comment on lines +1248 to +1249
exec.shared_data_->async_invoke(
HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Calling sync_invoke instead saves creating a ready-future that is discarded right away.

Suggested change
exec.shared_data_->async_invoke(
HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...);
exec.shared_data_->sync_invoke(
HPX_FORWARD(F, f), HPX_FORWARD(Ts, ts)...);

template <>
struct is_bulk_two_way_executor<fork_join_executor> : std::true_type
{
};
Copy link
Copy Markdown
Contributor

@hkaiser hkaiser May 9, 2026

Choose a reason for hiding this comment

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

Since you have added an implementation of post_t, we can also add:

    template <>
    struct is_never_blocking_one_way_executor<fork_join_executor> : std::true_type
    {
    };

#include <hpx/algorithm.hpp>
#include <hpx/chrono.hpp>
#include <hpx/execution.hpp>
#include <hpx/executors/executor_scheduler.hpp>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please never #include any of the module-internal headers directly. This will cause problems whenever C++ modules are enabled.

Suggested change
#include <hpx/executors/executor_scheduler.hpp>
#include <hpx/modules/executors.hpp>

HPX_CXX_CORE_EXPORT template <typename Executor, typename Receiver>
struct executor_operation_state;

} // namespace hpx::execution::experimental
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is no need to place this header into its own directory. It already has _fwd in its name.

@shivansh023023
Copy link
Copy Markdown
Contributor Author

Thank you for the reviews! I have addressed all feedback:

Replaced async_invoke with sync_invoke in the post_t overload
to avoid creating a ready-future that is immediately discarded.

Moved executor_scheduler_fwd.hpp out of the fwd/ subdirectory
since the _fwd suffix already conveys its purpose.

Replaced the internal #include <hpx/executors/executor_scheduler.hpp>
in the test file with #include <hpx/modules/executors.hpp>.

I initially added is_one_way_executor<fork_join_executor> as suggested,
but it caused the existing bulk dispatch chain to route through
sync_execute, which fork_join_executor does not implement — it is
bulk-only. All existing bulk tests failed as a result. I have reverted
this specialization. Happy to revisit if there is a preferred approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

category: senders/receivers Implementations of the p0443r14 / p2300 + p1897 proposals type: compatibility issue type: enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(Re-)Implement executor API on top of sender/receiver infrastructure

3 participants