blob: 4df755c2caca5351e543d75092ff3121b8122733 [file] [log] [blame]
Patrick Williams1f3a90f2023-05-19 16:03:04 -05001/*
2 * Copyright (c) 2021-2022 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 "../stdexec/execution.hpp"
19
Patrick Williams5932cd62023-11-16 11:13:00 -060020STDEXEC_PRAGMA_PUSH()
21STDEXEC_PRAGMA_IGNORE_EDG(1302)
Patrick Williams1f3a90f2023-05-19 16:03:04 -050022
23namespace exec
24{
Patrick Williams8723a542024-02-12 11:18:32 -060025template <class _Tag, class _Value>
26using with_t = stdexec::__env::__with<_Value, _Tag>;
Patrick Williams1f3a90f2023-05-19 16:03:04 -050027
Patrick Williams8723a542024-02-12 11:18:32 -060028namespace __envs
Patrick Williams1f3a90f2023-05-19 16:03:04 -050029{
30struct __with_t
31{
32 template <class _Tag, class _Value>
Patrick Williams1f7438a2024-01-23 16:54:44 -060033 auto operator()(_Tag, _Value&& __val) const
Patrick Williams1f3a90f2023-05-19 16:03:04 -050034 {
Patrick Williams1f7438a2024-01-23 16:54:44 -060035 return stdexec::__env::__with((_Value&&)__val, _Tag());
Patrick Williams1f3a90f2023-05-19 16:03:04 -050036 }
Patrick Williams1f7438a2024-01-23 16:54:44 -060037};
38
39struct __without_t
40{
Patrick Williams8723a542024-02-12 11:18:32 -060041 template <class _Env, class _Tag>
42 decltype(auto) operator()(_Env&& __env, _Tag) const
Patrick Williams1f7438a2024-01-23 16:54:44 -060043 {
Patrick Williams8723a542024-02-12 11:18:32 -060044 return stdexec::__env::__without((_Env&&)__env, _Tag());
Patrick Williams1f7438a2024-01-23 16:54:44 -060045 }
46};
47
48// For making an environment from key/value pairs and optionally
49// another environment.
50struct __make_env_t
51{
52 template <stdexec::__nothrow_move_constructible _Base,
53 stdexec::__nothrow_move_constructible _Env>
54 auto operator()(_Base&& __base, _Env&& __env) const noexcept
55 -> stdexec::__env::__join_t<_Env, _Base>
56 {
57 return stdexec::__env::__join((_Env&&)__env, (_Base&&)__base);
58 }
59
60 template <stdexec::__nothrow_move_constructible _Env>
61 _Env operator()(_Env&& __env) const noexcept
62 {
63 return (_Env&&)__env;
Patrick Williams1f3a90f2023-05-19 16:03:04 -050064 }
65};
Patrick Williams8723a542024-02-12 11:18:32 -060066} // namespace __envs
Patrick Williams1f3a90f2023-05-19 16:03:04 -050067
Patrick Williams8723a542024-02-12 11:18:32 -060068inline constexpr __envs::__with_t with{};
69inline constexpr __envs::__without_t without{};
70inline constexpr __envs::__make_env_t make_env{};
Patrick Williams1f3a90f2023-05-19 16:03:04 -050071
72template <class... _Ts>
Patrick Williams1f7438a2024-01-23 16:54:44 -060073using make_env_t = stdexec::__result_of<make_env, _Ts...>;
Patrick Williams1f3a90f2023-05-19 16:03:04 -050074
75namespace __read_with_default
76{
77using namespace stdexec;
78
79struct read_with_default_t;
80
81template <class _Tag, class _DefaultId, class _ReceiverId>
Patrick Williamsac329c52024-01-03 17:52:04 -060082struct __operation
Patrick Williams1f3a90f2023-05-19 16:03:04 -050083{
Patrick Williamsac329c52024-01-03 17:52:04 -060084 using _Default = stdexec::__t<_DefaultId>;
85 using _Receiver = stdexec::__t<_ReceiverId>;
Patrick Williams1f3a90f2023-05-19 16:03:04 -050086
Patrick Williamsac329c52024-01-03 17:52:04 -060087 struct __t : __immovable
Patrick Williams1f3a90f2023-05-19 16:03:04 -050088 {
Patrick Williamsac329c52024-01-03 17:52:04 -060089 using __id = __operation;
90
91 STDEXEC_ATTRIBUTE((no_unique_address)) _Default __default_;
92 _Receiver __rcvr_;
93
94 friend void tag_invoke(start_t, __t& __self) noexcept
Patrick Williams1f3a90f2023-05-19 16:03:04 -050095 {
Patrick Williamsac329c52024-01-03 17:52:04 -060096 try
Patrick Williams1f3a90f2023-05-19 16:03:04 -050097 {
Patrick Williamsac329c52024-01-03 17:52:04 -060098 if constexpr (__callable<_Tag, env_of_t<_Receiver>>)
99 {
100 const auto& __env = get_env(__self.__rcvr_);
101 set_value(std::move(__self.__rcvr_), _Tag{}(__env));
102 }
103 else
104 {
105 set_value(std::move(__self.__rcvr_),
106 std::move(__self.__default_));
107 }
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500108 }
Patrick Williamsac329c52024-01-03 17:52:04 -0600109 catch (...)
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500110 {
Patrick Williamsac329c52024-01-03 17:52:04 -0600111 set_error(std::move(__self.__rcvr_), std::current_exception());
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500112 }
113 }
Patrick Williamsac329c52024-01-03 17:52:04 -0600114 };
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500115};
116
Patrick Williamsac329c52024-01-03 17:52:04 -0600117template <class _Tag, class _Default, class _Receiver>
118using __operation_t = __t<__operation<_Tag, __id<_Default>, __id<_Receiver>>>;
119
120template <class _Tag, class _Default>
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500121struct __sender
122{
Patrick Williamsac329c52024-01-03 17:52:04 -0600123 using __id = __sender;
124 using __t = __sender;
Patrick Williams4c2d73d2023-12-01 16:58:58 -0600125 using sender_concept = stdexec::sender_t;
Patrick Williams5932cd62023-11-16 11:13:00 -0600126 STDEXEC_ATTRIBUTE((no_unique_address)) _Default __default_;
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500127
128 template <class _Env>
129 using __value_t = __minvoke<
130 __with_default<__mbind_back_q<__call_result_t, _Env>, _Default>, _Tag>;
131 template <class _Env>
132 using __default_t = __if_c<__callable<_Tag, _Env>, __ignore, _Default>;
133 template <class _Env>
134 using __completions_t =
135 completion_signatures<set_value_t(__value_t<_Env>),
136 set_error_t(std::exception_ptr)>;
137
138 template <__decays_to<__sender> _Self, class _Receiver>
139 requires receiver_of<_Receiver, __completions_t<env_of_t<_Receiver>>>
140 friend auto tag_invoke(connect_t, _Self&& __self, _Receiver __rcvr) //
141 noexcept(std::is_nothrow_move_constructible_v<_Receiver>)
Patrick Williamsac329c52024-01-03 17:52:04 -0600142 -> __operation_t<_Tag, __default_t<env_of_t<_Receiver>>, _Receiver>
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500143 {
144 return {{}, ((_Self&&)__self).__default_, (_Receiver&&)__rcvr};
145 }
146
Patrick Williams5932cd62023-11-16 11:13:00 -0600147 template <class _Env>
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500148 friend auto tag_invoke(get_completion_signatures_t, __sender, _Env&&)
Patrick Williams5932cd62023-11-16 11:13:00 -0600149 -> __completions_t<_Env>
150 {
151 return {};
152 }
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500153};
154
155struct __read_with_default_t
156{
157 template <class _Tag, class _Default>
158 constexpr auto operator()(_Tag, _Default&& __default) const
Patrick Williamsac329c52024-01-03 17:52:04 -0600159 -> __sender<_Tag, __decay_t<_Default>>
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500160 {
161 return {(_Default&&)__default};
162 }
163};
164} // namespace __read_with_default
165
166inline constexpr __read_with_default::__read_with_default_t read_with_default{};
167
Patrick Williams5932cd62023-11-16 11:13:00 -0600168inline constexpr stdexec::__write_::__write_t write{};
Patrick Williams1f3a90f2023-05-19 16:03:04 -0500169} // namespace exec
170
Patrick Williams5932cd62023-11-16 11:13:00 -0600171STDEXEC_PRAGMA_POP()