1 /*
2  * Copyright (c) 2021-2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__basic_sender.hpp"
19 #include "__diagnostics.hpp"
20 #include "__domain.hpp"
21 #include "__execution_fwd.hpp"
22 #include "__meta.hpp"
23 #include "__sender_adaptor_closure.hpp"
24 #include "__senders.hpp"
25 #include "__senders_core.hpp"
26 #include "__transform_completion_signatures.hpp"
27 #include "__transform_sender.hpp"
28 
29 // include these after __execution_fwd.hpp
30 namespace stdexec
31 {
32 /////////////////////////////////////////////////////////////////////////////
33 // [execution.senders.adaptors.then]
34 namespace __then
35 {
36 inline constexpr __mstring __then_context =
37     "In stdexec::then(Sender, Function)..."_mstr;
38 using __on_not_callable = __callable_error<__then_context>;
39 
40 template <class _Fun, class _CvrefSender, class... _Env>
41 using __completions_t = //
42     transform_completion_signatures<
43         __completion_signatures_of_t<_CvrefSender, _Env...>,
44         __with_error_invoke_t<__on_not_callable, set_value_t, _Fun,
45                               _CvrefSender, _Env...>,
46         __mbind_front<__mtry_catch_q<__set_value_invoke_t, __on_not_callable>,
47                       _Fun>::template __f>;
48 
49 ////////////////////////////////////////////////////////////////////////////////////////////////
50 struct then_t
51 {
52     template <sender _Sender, __movable_value _Fun>
operator ()stdexec::__then::then_t53     auto operator()(_Sender&& __sndr, _Fun __fun) const -> __well_formed_sender
54         auto
55     {
56         auto __domain = __get_early_domain(__sndr);
57         return stdexec::transform_sender(
58             __domain, __make_sexpr<then_t>(static_cast<_Fun&&>(__fun),
59                                            static_cast<_Sender&&>(__sndr)));
60     }
61 
62     template <__movable_value _Fun>
63     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__then::then_t64     auto operator()(_Fun __fun) const -> __binder_back<then_t, _Fun>
65     {
66         return {{static_cast<_Fun&&>(__fun)}, {}, {}};
67     }
68 
69     using _Sender = __1;
70     using _Fun = __0;
71     using __legacy_customizations_t =
72         __types<tag_invoke_t(then_t,
73                              get_completion_scheduler_t<set_value_t>(
74                                  get_env_t(_Sender&)),
75                              _Sender, _Fun),
76                 tag_invoke_t(then_t, _Sender, _Fun)>;
77 };
78 
79 struct __then_impl : __sexpr_defaults
80 {
81     static constexpr auto get_completion_signatures = //
82         []<class _Sender, class... _Env>(_Sender&&, _Env&&...) noexcept
83         -> __completions_t<__decay_t<__data_of<_Sender>>, __child_of<_Sender>,
84                            _Env...> {
85         static_assert(sender_expr_for<_Sender, then_t>);
86         return {};
87     };
88 
89     static constexpr auto complete = //
90         []<class _Tag, class _State, class _Receiver, class... _Args>(
91             __ignore, _State& __state, _Receiver& __rcvr, _Tag,
92             _Args&&... __args) noexcept -> void {
93         if constexpr (__same_as<_Tag, set_value_t>)
94         {
95             stdexec::__set_value_invoke(static_cast<_Receiver&&>(__rcvr),
96                                         static_cast<_State&&>(__state),
97                                         static_cast<_Args&&>(__args)...);
98         }
99         else
100         {
101             _Tag()(static_cast<_Receiver&&>(__rcvr),
102                    static_cast<_Args&&>(__args)...);
103         }
104     };
105 };
106 } // namespace __then
107 
108 using __then::then_t;
109 
110 /// @brief The then sender adaptor, which invokes a function with the result of
111 ///        a sender, making the result available to the next receiver.
112 /// @hideinitializer
113 inline constexpr then_t then{};
114 
115 template <>
116 struct __sexpr_impl<then_t> : __then::__then_impl
117 {};
118 } // namespace stdexec
119