-
-
Notifications
You must be signed in to change notification settings - Fork 543
actions_base: integrate reflect_action with basic_action #7281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -6,43 +6,52 @@ | |||||
|
|
||||||
| /// \file reflect_action.hpp | ||||||
| /// \brief Reflection-based action definition for HPX remote operations. | ||||||
| /// | ||||||
| /// This header provides reflect_action<F>, a C++26 reflection-based | ||||||
| /// replacement for the HPX_PLAIN_ACTION and HPX_REGISTER_ACTION macros. | ||||||
| /// Instead of verbose boilerplate, users write a single line: | ||||||
| /// | ||||||
| /// using compute_action = HPX_ACTION(app::compute); | ||||||
| /// | ||||||
| /// The action name, function pointer type, arity, and registration are | ||||||
| /// all derived automatically at compile time using C++26 static reflection. | ||||||
|
|
||||||
| #pragma once | ||||||
|
|
||||||
| #include <hpx/config.hpp> | ||||||
|
|
||||||
| #if defined(HPX_HAVE_CXX26_REFLECTION) | ||||||
|
|
||||||
| #include <hpx/actions_base/basic_action.hpp> | ||||||
| #include <hpx/actions_base/plain_action.hpp> | ||||||
| #include <hpx/serialization/detail/refl_qualified_name_of.hpp> | ||||||
|
|
||||||
| #include <cstddef> | ||||||
| #include <meta> | ||||||
| #include <string> | ||||||
| #include <type_traits> | ||||||
|
|
||||||
| namespace hpx::actions { | ||||||
|
|
||||||
| /// \cond NOINTERNAL | ||||||
| namespace detail { | ||||||
|
|
||||||
| /// Helper to extract function type from reflection for use | ||||||
| /// as basic_action template argument (two-step workaround for | ||||||
| /// GCC/Clang restriction on splice expressions as template args). | ||||||
| template <std::meta::info F> | ||||||
| struct reflect_action_base | ||||||
| { | ||||||
| using func_type = [:std::meta::type_of(F):]; | ||||||
| using type = basic_action<hpx::actions::detail::plain_function, | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This limits the use of |
||||||
| func_type, reflect_action_base<F>>; | ||||||
| }; | ||||||
|
|
||||||
| } // namespace detail | ||||||
| /// \endcond | ||||||
|
|
||||||
| /// \brief Reflection-based action template. | ||||||
| /// | ||||||
| /// reflect_action<F> provides the same interface as HPX_PLAIN_ACTION | ||||||
| /// but derives all properties automatically from the reflected function F: | ||||||
| /// - Qualified name via scope_builder<F> | ||||||
| /// - Function pointer type via std::meta::type_of(F) | ||||||
| /// - Function pointer via splicing [:F:] | ||||||
| /// - Arity via std::meta::parameters_of(F).size() | ||||||
| /// reflect_action<F> integrates with HPX's action system by inheriting | ||||||
| /// from basic_action<detail::plain_function, R(Ps...), reflect_action<F>>. | ||||||
| /// All properties are derived automatically from the reflected function F. | ||||||
| /// | ||||||
| /// \tparam F A std::meta::info reflection of a free function. | ||||||
| /// Obtain via the reflection operator: ^^app::my_function | ||||||
| template <std::meta::info F> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be now possible to write:
Suggested change
and reflect on the template argument wherever needed here? This would remove the need for the user to write |
||||||
| struct reflect_action | ||||||
| : basic_action<hpx::actions::detail::plain_function, | ||||||
| typename detail::reflect_action_base<F>::func_type, | ||||||
| reflect_action<F>> | ||||||
| { | ||||||
| /// The function type (e.g. int(double, double)) | ||||||
| using func_type = [:std::meta::type_of(F):]; | ||||||
|
|
@@ -57,16 +66,23 @@ namespace hpx::actions { | |||||
| static constexpr auto name_storage = | ||||||
| hpx::serialization::detail::scope_builder<F>::value; | ||||||
|
|
||||||
| /// Number of parameters the function takes | ||||||
| static constexpr std::size_t arity = std::meta::parameters_of(F).size(); | ||||||
| /// Returns the action name in HPX format: "plain action(app::compute)" | ||||||
| static std::string get_action_name( | ||||||
| naming::address::address_type /*lva*/) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the argument used for? Do we really need it?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, is there a way to avoid returning a |
||||||
| { | ||||||
| return hpx::actions::detail::make_plain_action_name( | ||||||
| std::string_view(name_storage.data, name_storage.size)); | ||||||
| } | ||||||
|
|
||||||
| /// Returns the fully qualified name of the action. | ||||||
| /// Called by hpx::actions::detail::register_action during | ||||||
| /// static initialization to register this action with the | ||||||
| /// HPX action registry. | ||||||
| static consteval char const* get_action_name() noexcept | ||||||
| /// Invokes the reflected function with the given arguments. | ||||||
| template <typename... Ts> | ||||||
| static auto invoke(naming::address::address_type /*lva*/, | ||||||
| naming::address::component_type /*comptype*/, Ts&&... vs) | ||||||
| { | ||||||
| return name_storage.data; | ||||||
| using base_t = basic_action<hpx::actions::detail::plain_function, | ||||||
| func_type, reflect_action<F>>; | ||||||
| base_t::increment_invocation_count(); | ||||||
| return func_ptr(HPX_FORWARD(Ts, vs)...); | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will have to be
in order to support C++20 module builds.