From 98d7153e1992f1f0281d329151d3f7d8aca2802b Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 11 Nov 2026 02:54:26 +0000 Subject: [PATCH] factor out common parts of the `then`/`upon_` algorithms --- include/nvexec/stream/then.cuh | 2 +- include/nvexec/stream/upon_error.cuh | 2 +- include/nvexec/stream/upon_stopped.cuh | 2 +- include/stdexec/__detail/__then.hpp | 31 ++---- .../__transform_completion_signatures.hpp | 23 ----- include/stdexec/__detail/__upon.hpp | 94 +++++++++++++++++++ include/stdexec/__detail/__upon_error.hpp | 30 ++---- include/stdexec/__detail/__upon_stopped.hpp | 31 ++---- 8 files changed, 117 insertions(+), 98 deletions(-) create mode 100644 include/stdexec/__detail/__upon.hpp diff --git a/include/nvexec/stream/then.cuh b/include/nvexec/stream/then.cuh index 084fbdf10..ce8fa0afd 100644 --- a/include/nvexec/stream/then.cuh +++ b/include/nvexec/stream/then.cuh @@ -176,7 +176,7 @@ namespace nv::execution::_strm { return exec::transform_completion_signatures( STDEXEC::get_completion_signatures<__copy_cvref_t, Env...>(), - STDEXEC::__transform_upon_completion(), + STDEXEC::__upon::__transform_completion(), {}, {}, _cuda_error_completion_t()); diff --git a/include/nvexec/stream/upon_error.cuh b/include/nvexec/stream/upon_error.cuh index 2086164b1..7535a290d 100644 --- a/include/nvexec/stream/upon_error.cuh +++ b/include/nvexec/stream/upon_error.cuh @@ -178,7 +178,7 @@ namespace nv::execution::_strm return exec::transform_completion_signatures( STDEXEC::get_completion_signatures<__copy_cvref_t, Env...>(), {}, - STDEXEC::__transform_upon_completion(), + STDEXEC::__upon::__transform_completion(), {}, _cuda_error_completion_t()); } diff --git a/include/nvexec/stream/upon_stopped.cuh b/include/nvexec/stream/upon_stopped.cuh index 20ea281ff..84e95cb97 100644 --- a/include/nvexec/stream/upon_stopped.cuh +++ b/include/nvexec/stream/upon_stopped.cuh @@ -167,7 +167,7 @@ namespace nv::execution::_strm STDEXEC::get_completion_signatures<__copy_cvref_t, Env...>(), {}, {}, - STDEXEC::__transform_upon_completion(), + STDEXEC::__upon::__transform_completion(), _cuda_error_completion_t()); } diff --git a/include/stdexec/__detail/__then.hpp b/include/stdexec/__detail/__then.hpp index b22e0abfd..27b724df2 100644 --- a/include/stdexec/__detail/__then.hpp +++ b/include/stdexec/__detail/__then.hpp @@ -26,13 +26,13 @@ import stdexec; # include "__execution_fwd.hpp" # include "__basic_sender.hpp" -# include "__completion_signatures_of.hpp" -# include "__diagnostics.hpp" # include "__meta.hpp" # include "__queries.hpp" # include "__sender_adaptor_closure.hpp" +# include "__sender_introspection.hpp" # include "__senders.hpp" # include "__transform_completion_signatures.hpp" +# include "__upon.hpp" # include "__prologue.hpp" @@ -43,7 +43,7 @@ namespace STDEXEC // [exec.then] namespace __then { - struct __then_impl : __sexpr_defaults + struct __impl : __sexpr_defaults { static constexpr auto __get_attrs = [](__ignore, __ignore, _Child const & __child) noexcept @@ -58,29 +58,10 @@ namespace STDEXEC using __fn_t = __decay_t<__data_of<_Sender>>; return STDEXEC::__transform_completion_signatures( STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), - __transform_upon_completion<__fn_t, then_t>()); + __upon::__transform_completion<__fn_t, then_t>()); } - struct __complete_fn - { - template - STDEXEC_ATTRIBUTE(host, device) - constexpr void operator()(__ignore, _State& __state, _Tag, _Args&&... __args) const noexcept - { - if constexpr (__same_as<_Tag, set_value_t>) - { - STDEXEC::__set_value_from(static_cast<_State&&>(__state).__rcvr_, - static_cast<_State&&>(__state).__data_, - static_cast<_Args&&>(__args)...); - } - else - { - _Tag()(static_cast<_State&&>(__state).__rcvr_, static_cast<_Args&&>(__args)...); - } - } - }; - - static constexpr auto __complete = __complete_fn{}; + static constexpr auto __complete = __upon::__complete; }; } // namespace __then @@ -225,7 +206,7 @@ namespace STDEXEC }; template <> - struct __sexpr_impl : __then::__then_impl + struct __sexpr_impl : __then::__impl {}; template diff --git a/include/stdexec/__detail/__transform_completion_signatures.hpp b/include/stdexec/__detail/__transform_completion_signatures.hpp index ce78c9fda..7b403a611 100644 --- a/include/stdexec/__detail/__transform_completion_signatures.hpp +++ b/include/stdexec/__detail/__transform_completion_signatures.hpp @@ -408,29 +408,6 @@ namespace STDEXEC } }; - STDEXEC_MODULE_EXPORT_AUTHORING - template - struct __transform_upon_completion - { - template - constexpr auto operator()() const - { - if constexpr (__nothrow_invocable<_Fun, _Args...>) - { - return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>>(); - } - else if constexpr (__invocable<_Fun, _Args...>) - { - return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>, - set_error_t(std::exception_ptr)>(); - } - else - { - return STDEXEC::__throw_compile_time_error(__callable_error_t()); - } - } - }; - //! @brief Transforms completion signatures using provided transformation //! functions. //! diff --git a/include/stdexec/__detail/__upon.hpp b/include/stdexec/__detail/__upon.hpp new file mode 100644 index 000000000..1cd4a4702 --- /dev/null +++ b/include/stdexec/__detail/__upon.hpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-2024 NVIDIA Corporation + * + * Licensed under the Apache License Version 2.0 with LLVM Exceptions + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "__config.hpp" + +#if STDEXEC_USE_MODULES() && !defined(STDEXEC_IN_MODULE_PURVIEW) + +import stdexec; + +#else + +# include "__execution_fwd.hpp" + +# include "../functional.hpp" +# include "__completion_signatures.hpp" +# include "__concepts.hpp" +# include "__diagnostics.hpp" +# include "__meta.hpp" +# include "__partition_completion_signatures.hpp" +# include "__receivers.hpp" + +# if !STDEXEC_USE_MODULES() +# include +# endif + +# include "__prologue.hpp" + +// NOLINTNEXTLINE(bugprone-std-namespace-modification, modernize-concat-nested-namespaces) +namespace STDEXEC +{ + ////////////////////////////////////////////////////////////////////////////// + // Helpers for [exec.then] + namespace __upon + { + template + static constexpr auto __complete = + [](__ignore, + _State& __state, + _Tag, + _Args&&... __args) noexcept -> void + { + if constexpr (__same_as<_Tag, _SetTag>) + { + STDEXEC::__set_value_from(static_cast<_State&&>(__state).__rcvr_, + static_cast<_State&&>(__state).__data_, + static_cast<_Args&&>(__args)...); + } + else + { + _Tag()(static_cast<_State&&>(__state).__rcvr_, static_cast<_Args&&>(__args)...); + } + }; + + STDEXEC_MODULE_EXPORT_AUTHORING + template + struct __transform_completion + { + template + constexpr auto operator()() const + { + if constexpr (__nothrow_invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>>(); + } + else if constexpr (__invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>, + set_error_t(std::exception_ptr)>(); + } + else + { + return STDEXEC::__throw_compile_time_error(__callable_error_t()); + } + } + }; + } // namespace __upon +} // namespace STDEXEC + +# include "__epilogue.hpp" +#endif // !STDEXEC_USE_MODULES() || defined(STDEXEC_IN_MODULE_PURVIEW) diff --git a/include/stdexec/__detail/__upon_error.hpp b/include/stdexec/__detail/__upon_error.hpp index 5bbafd08b..7c4bdc2b2 100644 --- a/include/stdexec/__detail/__upon_error.hpp +++ b/include/stdexec/__detail/__upon_error.hpp @@ -26,13 +26,13 @@ import stdexec; # include "__execution_fwd.hpp" # include "__basic_sender.hpp" -# include "__completion_signatures_of.hpp" -# include "__diagnostics.hpp" # include "__meta.hpp" # include "__queries.hpp" # include "__sender_adaptor_closure.hpp" -# include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender +# include "__sender_introspection.hpp" +# include "__senders.hpp" # include "__transform_completion_signatures.hpp" +# include "__upon.hpp" # include "__prologue.hpp" @@ -43,7 +43,7 @@ namespace STDEXEC // [exec.then] namespace __upon_error { - struct __upon_error_impl : __sexpr_defaults + struct __impl : __sexpr_defaults { static constexpr auto __get_attrs = [](__ignore, __ignore, _Child const & __child) noexcept @@ -59,26 +59,10 @@ namespace STDEXEC return STDEXEC::__transform_completion_signatures( STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), {}, - __transform_upon_completion<__fn_t, upon_error_t>()); + __upon::__transform_completion<__fn_t, upon_error_t>()); } - static constexpr auto __complete = - [](__ignore, - _State& __state, - _Tag, - _Args&&... __args) noexcept -> void - { - if constexpr (__same_as<_Tag, set_error_t>) - { - STDEXEC::__set_value_from(static_cast<_State&&>(__state).__rcvr_, - static_cast<_State&&>(__state).__data_, - static_cast<_Args&&>(__args)...); - } - else - { - _Tag()(static_cast<_State&&>(__state).__rcvr_, static_cast<_Args&&>(__args)...); - } - }; + static constexpr auto __complete = __upon::__complete; }; } // namespace __upon_error @@ -225,7 +209,7 @@ namespace STDEXEC }; template <> - struct __sexpr_impl : __upon_error::__upon_error_impl + struct __sexpr_impl : __upon_error::__impl {}; template diff --git a/include/stdexec/__detail/__upon_stopped.hpp b/include/stdexec/__detail/__upon_stopped.hpp index aa012bd38..80c721d3c 100644 --- a/include/stdexec/__detail/__upon_stopped.hpp +++ b/include/stdexec/__detail/__upon_stopped.hpp @@ -26,11 +26,11 @@ import stdexec; # include "__execution_fwd.hpp" # include "__basic_sender.hpp" -# include "__completion_signatures_of.hpp" -# include "__meta.hpp" # include "__sender_adaptor_closure.hpp" -# include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender +# include "__sender_introspection.hpp" +# include "__senders.hpp" # include "__transform_completion_signatures.hpp" +# include "__upon.hpp" # include "__prologue.hpp" @@ -41,7 +41,7 @@ namespace STDEXEC // [exec.then] namespace __upon_stopped { - struct __upon_stopped_impl : __sexpr_defaults + struct __impl : __sexpr_defaults { template static consteval auto __get_completion_signatures() @@ -52,27 +52,10 @@ namespace STDEXEC STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), {}, {}, - __always{__set_value_from_t<__fn_t>()}, - __eptr_completion_unless_t<__mbool<__nothrow_callable<__fn_t>>>()); + __upon::__transform_completion<__fn_t, upon_stopped_t>()); } - static constexpr auto __complete = - [](__ignore, - _State& __state, - _Tag, - _Args&&... __args) noexcept -> void - { - if constexpr (__same_as<_Tag, set_stopped_t>) - { - STDEXEC::__set_value_from(static_cast<_State&&>(__state).__rcvr_, - static_cast<_State&&>(__state).__data_, - static_cast<_Args&&>(__args)...); - } - else - { - _Tag()(static_cast<_State&&>(__state).__rcvr_, static_cast<_Args&&>(__args)...); - } - }; + static constexpr auto __complete = __upon::__complete; }; } // namespace __upon_stopped @@ -215,7 +198,7 @@ namespace STDEXEC }; template <> - struct __sexpr_impl : __upon_stopped::__upon_stopped_impl + struct __sexpr_impl : __upon_stopped::__impl {}; template