kokkos-execution 0.0.1
Loading...
Searching...
No Matches
within.hpp
Go to the documentation of this file.
1// NOLINTBEGIN
2/*
3 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 * Copyright (c) 2025 Robert Leahy. All rights reserved.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 * Licensed under the Apache License, Version 2.0 with LLVM Exceptions (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * https://llvm.org/LICENSE.txt
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#pragma once
21
22#include <tuple>
23#include <type_traits>
24#include <utility>
25#include <variant>
26
27#include "elide.hpp"
29#include "stdexec/execution.hpp"
31
33
34namespace detail::within {
35
36struct t {
37 template <::exec::enter_scope_sender Scope, ::STDEXEC::sender Sender>
38 constexpr ::STDEXEC::sender auto operator()(Scope&& scope, Sender&& sender) const noexcept(
39 std::is_nothrow_constructible_v<std::remove_cvref_t<Scope>, Scope>
40 && std::is_nothrow_constructible_v<std::remove_cvref_t<Sender>, Sender>) {
41 return ::STDEXEC::__sexpr{t(), ::STDEXEC::__(), (Scope&&) scope, (Sender&&) sender};
42 }
43};
44
45template <typename...>
46using remove_set_value_t = ::STDEXEC::completion_signatures<>;
47
48template <typename Sender, typename Env>
49inline constexpr bool nothrow_connect_sender =
50 ::STDEXEC::__nothrow_connectable<Sender, ::STDEXEC::__receiver_archetype<Env>> &&
51 // Because we move the sender out of storage so we can reuse it
52 std::is_nothrow_move_constructible_v<Sender>;
53
54template <typename Sender, typename Env>
55using completion_signatures_of_sender_t = ::STDEXEC::transform_completion_signatures<
56 ::STDEXEC::completion_signatures_of_t<Sender, Env>,
57 std::conditional_t<
59 ::STDEXEC::completion_signatures<>,
60 ::STDEXEC::completion_signatures<::STDEXEC::set_error_t(std::exception_ptr)>
61 >
62>;
63
64template <typename Scope, typename... Env>
65using completion_signatures_of_scope_t = ::STDEXEC::transform_completion_signatures<
66 ::STDEXEC::completion_signatures_of_t<Scope, Env...>,
67 ::STDEXEC::completion_signatures<>,
69>;
70
71template <typename Sender, typename Env>
73 ::exec::storage_for_completion_signatures<completion_signatures_of_sender_t<Sender, Env>>;
74
75template <typename Env>
77 template <typename Scope, typename Sender>
78 using __f = ::STDEXEC::transform_completion_signatures<
79 typename storage_for_completion_signatures_t<std::remove_cvref_t<Sender>, Env>::completion_signatures,
81 >;
82};
83
84template <typename Scope, typename Sender, typename Receiver>
85class state {
86 using env_type_ = ::STDEXEC::env_of_t<Receiver>;
87
89 using receiver_concept = ::STDEXEC::receiver_t;
90 constexpr env_type_ get_env() const noexcept;
92 };
93
95
98 constexpr void set_value(exit_scope_sender_type_) && noexcept;
99 template <typename... Args>
100 constexpr void set_error(Args&&...) && noexcept;
101 template <typename... Args>
102 constexpr void set_stopped(Args&&...) && noexcept;
103 };
104
105 using enter_operation_state_type_ = ::STDEXEC::connect_result_t<Scope, enter_receiver_type_>;
106
109 constexpr void set_value() && noexcept;
110 };
111
112 using exit_operation_state_type_ = ::STDEXEC::connect_result_t<exit_scope_sender_type_, exit_receiver_type_>;
113
116 template <typename... Args>
117 constexpr void set_value(Args&&...) && noexcept;
118 template <typename... Args>
119 constexpr void set_error(Args&&...) && noexcept;
120 template <typename... Args>
121 constexpr void set_stopped(Args&&...) && noexcept;
122 };
123
124 using operation_state_type_ = ::STDEXEC::connect_result_t<Sender, receiver_type_>;
125 Receiver r_;
127
132
137
138 std::variant<enter_state_type_, state_type_, exit_operation_state_type_> state_;
139
140 constexpr void exit_() noexcept {
141 const auto ptr = std::get_if<state_type_>(&state_);
142 auto sender = std::move(ptr->s);
143 auto&& op = state_.template emplace<exit_operation_state_type_>(::exec::elide(
144 [&]() noexcept { return ::STDEXEC::connect(std::move(sender), exit_receiver_type_{{*this}}); }));
145 ::STDEXEC::start(op);
146 }
147
148 template <typename... Args>
149 constexpr void complete_(Args&&... args) noexcept {
150 storage_.arrive((Args&&) args...);
151 exit_();
152 }
153
154 static constexpr bool nothrow_construct_connect_ = ::STDEXEC::__nothrow_connectable<Scope, enter_receiver_type_>;
155 public:
156 template <typename S>
157 explicit constexpr state(Scope&& scope, S&& sender, Receiver r)
158 noexcept(std::is_nothrow_constructible_v<Sender, S> && nothrow_construct_connect_)
159 : r_((Receiver&&) r)
160 , state_(std::in_place_type<enter_state_type_>, ::exec::elide([&]() noexcept(nothrow_construct_connect_) {
161 return enter_state_type_{
162 ::STDEXEC::connect((Scope&&) scope, enter_receiver_type_{{*this}}), (S&&) sender};
163 })) {
164 }
165
166 constexpr void start() & noexcept {
167 const auto ptr = std::get_if<enter_state_type_>(&state_);
168 STDEXEC_ASSERT(ptr);
169 ::STDEXEC::start(ptr->op);
170 }
171};
172
173template <typename Scope, typename Sender, typename Receiver>
175 return ::STDEXEC::get_env(self_.r_);
176}
177
178template <typename Scope, typename Sender, typename Receiver>
179constexpr void
181 // Because we're going to destroy the operation state and therefore
182 // transitively *this
183 auto&& self = self_;
184 constexpr auto nothrow = nothrow_connect_sender<Sender, env_type_>;
185 const auto ptr = std::get_if<enter_state_type_>(&self.state_);
186 STDEXEC_ASSERT(ptr);
187 try {
188 auto sender = (Sender&&) ptr->s;
189 auto&& state = self.state_.template emplace<state_type_>(::exec::elide([&]() noexcept(nothrow) {
190 return state_type_{::STDEXEC::connect((Sender&&) sender, receiver_type_{{self}}), std::move(exit)};
191 }));
192 ::STDEXEC::start(state.op);
193 } catch (...) {
194 if constexpr (nothrow) {
195 STDEXEC_UNREACHABLE();
196 } else {
197 ::STDEXEC::set_error((Receiver&&) self.r_, std::current_exception());
198 }
199 }
200}
201
202template <typename Scope, typename Sender, typename Receiver>
203template <typename... Args>
204constexpr void state<Scope, Sender, Receiver>::enter_receiver_type_::set_error(Args&&... args) && noexcept {
205 ::STDEXEC::set_error((Receiver&&) self_.r_, (Args&&) args...);
206}
207
208template <typename Scope, typename Sender, typename Receiver>
209template <typename... Args>
211 ::STDEXEC::set_stopped((Receiver&&) self_.r_, (Args&&) args...);
212}
213
214template <typename Scope, typename Sender, typename Receiver>
216 std::move(self_.storage_).complete((Receiver&&) self_.r_);
217}
218
219template <typename Scope, typename Sender, typename Receiver>
220template <typename... Args>
221constexpr void state<Scope, Sender, Receiver>::receiver_type_::set_value(Args&&... args) && noexcept {
222 self_.complete_(::STDEXEC::set_value, (Args&&) args...);
223}
224
225template <typename Scope, typename Sender, typename Receiver>
226template <typename... Args>
227constexpr void state<Scope, Sender, Receiver>::receiver_type_::set_error(Args&&... args) && noexcept {
228 self_.complete_(::STDEXEC::set_error, (Args&&) args...);
229}
230
231template <typename Scope, typename Sender, typename Receiver>
232template <typename... Args>
233constexpr void state<Scope, Sender, Receiver>::receiver_type_::set_stopped(Args&&... args) && noexcept {
234 self_.complete_(::STDEXEC::set_stopped, (Args&&) args...);
235}
236
237// TODO: We should be able to get a better "message" than this
239
240template <typename Receiver>
242 template <typename Scope, typename Sender>
244};
245
246template <typename Receiver>
248 template <typename Scope, typename Sender>
249 using __f = std::is_nothrow_constructible<
251 Scope,
252 Sender,
253 Receiver
254 >;
255};
256
257class impl : public ::STDEXEC::__sexpr_defaults {
258 template <typename Sender, typename... Env>
259 using completions_ = ::STDEXEC::__children_of<Sender, completions<Env...>>;
260 public:
261 template <typename Sender, typename... Env>
262 static consteval auto __get_completion_signatures() {
263 if constexpr (sizeof...(Env) == 0) {
264 return STDEXEC::__throw_dependent_sender_error<Sender>();
265 } else if constexpr (::STDEXEC::__minvocable_q<completions_, Sender, Env...>) {
266 return completions_<Sender, Env...>{};
267 } else {
268 return ::STDEXEC::__throw_compile_time_error<
270 ::STDEXEC::_WITH_SENDER_<Sender>
271 >();
272 }
273 }
274
275 static constexpr auto __connect = []<typename Sender, typename Receiver>(Sender&& sender, Receiver r) noexcept(
276 ::STDEXEC::__children_of<Sender, nothrow_connect<Receiver>>::value)
277 -> ::STDEXEC::__children_of<Sender, connect_result<Receiver>> {
278 return ::STDEXEC::__apply(
279 [&](auto&&, auto&&, auto&& scope, auto&& sender) noexcept(
280 ::STDEXEC::__children_of<Sender, nothrow_connect<Receiver>>::value)
281 -> ::STDEXEC::__children_of<Sender, connect_result<Receiver>> {
282 return ::STDEXEC::__children_of<Sender, connect_result<Receiver>>(
283 (decltype(scope)&&) scope, (decltype(sender)&&) sender, (Receiver&&) r);
284 },
285 (Sender&&) sender);
286 };
287};
288
289} // namespace detail::within
290
292inline constexpr within_t within;
293
294} // namespace experimental::execution
295
296namespace STDEXEC {
297
298template <>
299struct __sexpr_impl<::exec::within_t> : ::exec::detail::within::impl { };
300
301} // namespace STDEXEC
302
303// NOLINTEND
::stdexec::__children_of< Sender, completions< Env... > > completions_
Definition within.hpp:259
static consteval auto __get_completion_signatures()
Definition within.hpp:262
::stdexec::connect_result_t< Sender, receiver_type_ > operation_state_type_
Definition within.hpp:124
constexpr void complete_(Args &&... args) noexcept
Definition within.hpp:149
::stdexec::env_of_t< Receiver > env_type_
Definition within.hpp:86
std::variant< enter_state_type_, state_type_, exit_operation_state_type_ > state_
Definition within.hpp:138
::stdexec::connect_result_t< exit_scope_sender_type_, exit_receiver_type_ > exit_operation_state_type_
Definition within.hpp:112
::stdexec::connect_result_t< Scope, enter_receiver_type_ > enter_operation_state_type_
Definition within.hpp:105
::exec::exit_scope_sender_of_t< Scope, env_type_ > exit_scope_sender_type_
Definition within.hpp:94
constexpr state(Scope &&scope, S &&sender, Receiver r) noexcept(std::is_nothrow_constructible_v< Sender, S > &&nothrow_construct_connect_)
Definition within.hpp:157
::stdexec::transform_completion_signatures< ::stdexec::completion_signatures_of_t< Scope, Env... >, ::stdexec::completion_signatures<>, remove_set_value_t > completion_signatures_of_scope_t
Definition within.hpp:65
::stdexec::completion_signatures<> remove_set_value_t
Definition within.hpp:46
::stdexec::transform_completion_signatures< ::stdexec::completion_signatures_of_t< Sender, Env >, std::conditional_t< nothrow_connect_sender< Sender, Env >, ::stdexec::completion_signatures<>, ::stdexec::completion_signatures<::stdexec::set_error_t(std::exception_ptr)> > > completion_signatures_of_sender_t
Definition within.hpp:55
::exec::storage_for_completion_signatures< completion_signatures_of_sender_t< Sender, Env > > storage_for_completion_signatures_t
Definition within.hpp:72
detail::within::t within_t
Definition within.hpp:291
constexpr within_t within
Definition within.hpp:292
detail::exit_scope_sender_of::impl<::stdexec::transform_completion_signatures< ::stdexec::completion_signatures_of_t< Constructor, Env >, ::stdexec::completion_signatures<>, detail::exit_scope_sender_of::transform_set_value< Env >::template fn, detail::exit_scope_sender_of::transform_set_error, ::stdexec::completion_signatures<> > >::type exit_scope_sender_of_t
::stdexec::transform_completion_signatures< typename storage_for_completion_signatures_t< std::remove_cvref_t< Sender >, Env >::completion_signatures, completion_signatures_of_scope_t< Scope, Env > > __f
Definition within.hpp:78
state< Scope, std::remove_cvref_t< Sender >, Receiver > __f
Definition within.hpp:243
std::is_nothrow_constructible< typename connect_result< Receiver >::template __f< Scope, Sender >, Scope, Sender, Receiver > __f
Definition within.hpp:249
constexpr ::stdexec::sender auto operator()(Scope &&scope, Sender &&sender) const noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Scope >, Scope > &&std::is_nothrow_constructible_v< std::remove_cvref_t< Sender >, Sender >)
Definition within.hpp:38