Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 1 | /* |
| 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 Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 20 | STDEXEC_PRAGMA_PUSH() |
| 21 | STDEXEC_PRAGMA_IGNORE_EDG(1302) |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 22 | |
| 23 | namespace exec |
| 24 | { |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 25 | template <class _Tag, class _Value> |
| 26 | using with_t = stdexec::__env::__with<_Value, _Tag>; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 27 | |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 28 | namespace __envs |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 29 | { |
| 30 | struct __with_t |
| 31 | { |
| 32 | template <class _Tag, class _Value> |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 33 | auto operator()(_Tag, _Value&& __val) const |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 34 | { |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 35 | return stdexec::__env::__with((_Value&&)__val, _Tag()); |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 36 | } |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 37 | }; |
| 38 | |
| 39 | struct __without_t |
| 40 | { |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 41 | template <class _Env, class _Tag> |
| 42 | decltype(auto) operator()(_Env&& __env, _Tag) const |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 43 | { |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 44 | return stdexec::__env::__without((_Env&&)__env, _Tag()); |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 45 | } |
| 46 | }; |
| 47 | |
| 48 | // For making an environment from key/value pairs and optionally |
| 49 | // another environment. |
| 50 | struct __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 Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 64 | } |
| 65 | }; |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 66 | } // namespace __envs |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 67 | |
Patrick Williams | 8723a54 | 2024-02-12 11:18:32 -0600 | [diff] [blame^] | 68 | inline constexpr __envs::__with_t with{}; |
| 69 | inline constexpr __envs::__without_t without{}; |
| 70 | inline constexpr __envs::__make_env_t make_env{}; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 71 | |
| 72 | template <class... _Ts> |
Patrick Williams | 1f7438a | 2024-01-23 16:54:44 -0600 | [diff] [blame] | 73 | using make_env_t = stdexec::__result_of<make_env, _Ts...>; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 74 | |
| 75 | namespace __read_with_default |
| 76 | { |
| 77 | using namespace stdexec; |
| 78 | |
| 79 | struct read_with_default_t; |
| 80 | |
| 81 | template <class _Tag, class _DefaultId, class _ReceiverId> |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 82 | struct __operation |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 83 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 84 | using _Default = stdexec::__t<_DefaultId>; |
| 85 | using _Receiver = stdexec::__t<_ReceiverId>; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 86 | |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 87 | struct __t : __immovable |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 88 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 89 | 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 Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 95 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 96 | try |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 97 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 98 | 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 Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 108 | } |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 109 | catch (...) |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 110 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 111 | set_error(std::move(__self.__rcvr_), std::current_exception()); |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 112 | } |
| 113 | } |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 114 | }; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 115 | }; |
| 116 | |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 117 | template <class _Tag, class _Default, class _Receiver> |
| 118 | using __operation_t = __t<__operation<_Tag, __id<_Default>, __id<_Receiver>>>; |
| 119 | |
| 120 | template <class _Tag, class _Default> |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 121 | struct __sender |
| 122 | { |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 123 | using __id = __sender; |
| 124 | using __t = __sender; |
Patrick Williams | 4c2d73d | 2023-12-01 16:58:58 -0600 | [diff] [blame] | 125 | using sender_concept = stdexec::sender_t; |
Patrick Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 126 | STDEXEC_ATTRIBUTE((no_unique_address)) _Default __default_; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 127 | |
| 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 Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 142 | -> __operation_t<_Tag, __default_t<env_of_t<_Receiver>>, _Receiver> |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 143 | { |
| 144 | return {{}, ((_Self&&)__self).__default_, (_Receiver&&)__rcvr}; |
| 145 | } |
| 146 | |
Patrick Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 147 | template <class _Env> |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 148 | friend auto tag_invoke(get_completion_signatures_t, __sender, _Env&&) |
Patrick Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 149 | -> __completions_t<_Env> |
| 150 | { |
| 151 | return {}; |
| 152 | } |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 153 | }; |
| 154 | |
| 155 | struct __read_with_default_t |
| 156 | { |
| 157 | template <class _Tag, class _Default> |
| 158 | constexpr auto operator()(_Tag, _Default&& __default) const |
Patrick Williams | ac329c5 | 2024-01-03 17:52:04 -0600 | [diff] [blame] | 159 | -> __sender<_Tag, __decay_t<_Default>> |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 160 | { |
| 161 | return {(_Default&&)__default}; |
| 162 | } |
| 163 | }; |
| 164 | } // namespace __read_with_default |
| 165 | |
| 166 | inline constexpr __read_with_default::__read_with_default_t read_with_default{}; |
| 167 | |
Patrick Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 168 | inline constexpr stdexec::__write_::__write_t write{}; |
Patrick Williams | 1f3a90f | 2023-05-19 16:03:04 -0500 | [diff] [blame] | 169 | } // namespace exec |
| 170 | |
Patrick Williams | 5932cd6 | 2023-11-16 11:13:00 -0600 | [diff] [blame] | 171 | STDEXEC_PRAGMA_POP() |