15cee9157SPatrick Williams /*
25cee9157SPatrick Williams  * Copyright (c) 2021-2024 NVIDIA Corporation
35cee9157SPatrick Williams  *
45cee9157SPatrick Williams  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
55cee9157SPatrick Williams  * (the "License"); you may not use this file except in compliance with
65cee9157SPatrick Williams  * the License. You may obtain a copy of the License at
75cee9157SPatrick Williams  *
85cee9157SPatrick Williams  *   https://llvm.org/LICENSE.txt
95cee9157SPatrick Williams  *
105cee9157SPatrick Williams  * Unless required by applicable law or agreed to in writing, software
115cee9157SPatrick Williams  * distributed under the License is distributed on an "AS IS" BASIS,
125cee9157SPatrick Williams  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135cee9157SPatrick Williams  * See the License for the specific language governing permissions and
145cee9157SPatrick Williams  * limitations under the License.
155cee9157SPatrick Williams  */
165cee9157SPatrick Williams #pragma once
175cee9157SPatrick Williams 
185cee9157SPatrick Williams #include "__basic_sender.hpp"
195cee9157SPatrick Williams #include "__diagnostics.hpp"
205cee9157SPatrick Williams #include "__domain.hpp"
215cee9157SPatrick Williams #include "__execution_fwd.hpp"
225cee9157SPatrick Williams #include "__meta.hpp"
235cee9157SPatrick Williams #include "__sender_adaptor_closure.hpp"
245cee9157SPatrick Williams #include "__senders.hpp"
255cee9157SPatrick Williams #include "__senders_core.hpp"
265cee9157SPatrick Williams #include "__transform_completion_signatures.hpp"
275cee9157SPatrick Williams #include "__transform_sender.hpp"
285cee9157SPatrick Williams 
295cee9157SPatrick Williams // include these after __execution_fwd.hpp
305cee9157SPatrick Williams namespace stdexec
315cee9157SPatrick Williams {
325cee9157SPatrick Williams /////////////////////////////////////////////////////////////////////////////
335cee9157SPatrick Williams // [execution.senders.adaptors.upon_stopped]
345cee9157SPatrick Williams namespace __upon_stopped
355cee9157SPatrick Williams {
365cee9157SPatrick Williams inline constexpr __mstring __upon_stopped_context =
375cee9157SPatrick Williams     "In stdexec::upon_stopped(Sender, Function)..."_mstr;
385cee9157SPatrick Williams using __on_not_callable = __callable_error<__upon_stopped_context>;
395cee9157SPatrick Williams 
405cee9157SPatrick Williams template <class _Fun, class _CvrefSender, class... _Env>
415cee9157SPatrick Williams using __completion_signatures_t = //
425cee9157SPatrick Williams     transform_completion_signatures<
435cee9157SPatrick Williams         __completion_signatures_of_t<_CvrefSender, _Env...>,
445cee9157SPatrick Williams         __with_error_invoke_t<__on_not_callable, set_stopped_t, _Fun,
455cee9157SPatrick Williams                               _CvrefSender, _Env...>,
465cee9157SPatrick Williams         __sigs::__default_set_value, __sigs::__default_set_error,
475cee9157SPatrick Williams         __set_value_invoke_t<_Fun>>;
485cee9157SPatrick Williams 
495cee9157SPatrick Williams ////////////////////////////////////////////////////////////////////////////////////////////////
505cee9157SPatrick Williams struct upon_stopped_t
515cee9157SPatrick Williams {
525cee9157SPatrick Williams     template <sender _Sender, __movable_value _Fun>
535cee9157SPatrick Williams         requires __callable<_Fun>
operator ()stdexec::__upon_stopped::upon_stopped_t545cee9157SPatrick Williams     auto operator()(_Sender&& __sndr, _Fun __fun) const -> __well_formed_sender
555cee9157SPatrick Williams         auto
565cee9157SPatrick Williams     {
575cee9157SPatrick Williams         auto __domain = __get_early_domain(__sndr);
585cee9157SPatrick Williams         return stdexec::transform_sender(
595cee9157SPatrick Williams             __domain,
605cee9157SPatrick Williams             __make_sexpr<upon_stopped_t>(static_cast<_Fun&&>(__fun),
615cee9157SPatrick Williams                                          static_cast<_Sender&&>(__sndr)));
625cee9157SPatrick Williams     }
635cee9157SPatrick Williams 
645cee9157SPatrick Williams     template <__movable_value _Fun>
655cee9157SPatrick Williams         requires __callable<_Fun>
66*06f265f6SPatrick Williams     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__upon_stopped::upon_stopped_t67*06f265f6SPatrick Williams     auto operator()(_Fun __fun) const -> __binder_back<upon_stopped_t, _Fun>
685cee9157SPatrick Williams     {
695cee9157SPatrick Williams         return {{static_cast<_Fun&&>(__fun)}, {}, {}};
705cee9157SPatrick Williams     }
715cee9157SPatrick Williams 
725cee9157SPatrick Williams     using _Sender = __1;
735cee9157SPatrick Williams     using _Fun = __0;
745cee9157SPatrick Williams     using __legacy_customizations_t =
755cee9157SPatrick Williams         __types<tag_invoke_t(upon_stopped_t,
765cee9157SPatrick Williams                              get_completion_scheduler_t<set_value_t>(
775cee9157SPatrick Williams                                  get_env_t(_Sender&)),
785cee9157SPatrick Williams                              _Sender, _Fun),
795cee9157SPatrick Williams                 tag_invoke_t(upon_stopped_t, _Sender, _Fun)>;
805cee9157SPatrick Williams };
815cee9157SPatrick Williams 
825cee9157SPatrick Williams struct __upon_stopped_impl : __sexpr_defaults
835cee9157SPatrick Williams {
845cee9157SPatrick Williams     static constexpr auto get_completion_signatures = //
855cee9157SPatrick Williams         []<class _Sender, class... _Env>(_Sender&&, _Env&&...) noexcept
865cee9157SPatrick Williams         -> __completion_signatures_t<__decay_t<__data_of<_Sender>>,
875cee9157SPatrick Williams                                      __child_of<_Sender>, _Env...> {
885cee9157SPatrick Williams         static_assert(sender_expr_for<_Sender, upon_stopped_t>);
895cee9157SPatrick Williams         return {};
905cee9157SPatrick Williams     };
915cee9157SPatrick Williams 
925cee9157SPatrick Williams     static constexpr auto complete = //
935cee9157SPatrick Williams         []<class _Tag, class _State, class _Receiver, class... _Args>(
945cee9157SPatrick Williams             __ignore, _State& __state, _Receiver& __rcvr, _Tag,
955cee9157SPatrick Williams             _Args&&... __args) noexcept -> void {
965cee9157SPatrick Williams         if constexpr (__same_as<_Tag, set_stopped_t>)
975cee9157SPatrick Williams         {
985cee9157SPatrick Williams             stdexec::__set_value_invoke(static_cast<_Receiver&&>(__rcvr),
995cee9157SPatrick Williams                                         static_cast<_State&&>(__state),
1005cee9157SPatrick Williams                                         static_cast<_Args&&>(__args)...);
1015cee9157SPatrick Williams         }
1025cee9157SPatrick Williams         else
1035cee9157SPatrick Williams         {
1045cee9157SPatrick Williams             _Tag()(static_cast<_Receiver&&>(__rcvr),
1055cee9157SPatrick Williams                    static_cast<_Args&&>(__args)...);
1065cee9157SPatrick Williams         }
1075cee9157SPatrick Williams     };
1085cee9157SPatrick Williams };
1095cee9157SPatrick Williams } // namespace __upon_stopped
1105cee9157SPatrick Williams 
1115cee9157SPatrick Williams using __upon_stopped::upon_stopped_t;
1125cee9157SPatrick Williams inline constexpr upon_stopped_t upon_stopped{};
1135cee9157SPatrick Williams 
1145cee9157SPatrick Williams template <>
1155cee9157SPatrick Williams struct __sexpr_impl<upon_stopped_t> : __upon_stopped::__upon_stopped_impl
1165cee9157SPatrick Williams {};
1175cee9157SPatrick Williams 
1185cee9157SPatrick Williams } // namespace stdexec
119