31#include "stdexec/execution.hpp"
41 template <::exec::enter_scope_sender... Senders>
42 constexpr ::exec::enter_scope_sender
auto operator()(Senders&&... senders)
const
43 noexcept((std::is_nothrow_constructible_v<std::remove_cvref_t<Senders>, Senders> && ...)) {
44 return ::STDEXEC::__sexpr{
t(), ::STDEXEC::__(), (Senders&&) senders...};
47 template <::exec::enter_scope_sender Sender>
48 constexpr ::exec::enter_scope_sender
auto operator()(Sender&& sender)
const
49 noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<Sender>, Sender>) {
50 return (Sender&&) sender;
53 constexpr ::exec::enter_scope_sender
auto operator()() const noexcept {
54 return ::STDEXEC::just(::STDEXEC::just());
58template <::exec::enter_scope_sender Sender,
typename Receiver,
typename RollbackReceiver>
68 auto base = (Receiver&&) *
this;
71 self.
storage_.template emplace<exit_scope_sender_type_>(std::move(sender));
72 ::STDEXEC::set_value(std::move(base));
80 std::variant<operation_state_type_, exit_scope_sender_type_, rollback_operation_state_type_>
storage_;
85 return ::STDEXEC::connect((Sender&&) sender, receiver_type_{{(Receiver&&) r}, *
this});
89 constexpr void start() &
noexcept {
90 const auto ptr = std::get_if<operation_state_type_>(&
storage_);
92 ::STDEXEC::start(*ptr);
97 const auto ptr = std::get_if<exit_scope_sender_type_>(&
storage_);
101 auto sender = std::move(*ptr);
102 storage_.template emplace<rollback_operation_state_type_>(
103 ::exec::elide([&]()
noexcept { return ::STDEXEC::connect(std::move(sender), std::move(r)); }));
108 if (
const auto ptr = std::get_if<rollback_operation_state_type_>(&
storage_); ptr) {
109 ::STDEXEC::start(*ptr);
114 const auto ptr = std::get_if<exit_scope_sender_type_>(&
storage_);
116 return std::move(*ptr);
120template <
typename...>
123template <
typename... Senders>
124using exit_sender_t =
decltype(::STDEXEC::when_all(std::declval<Senders>()...));
126template <
typename... Env>
128 template <
typename... Senders>
129 using __f = ::exec::storage_for_completion_signatures<::STDEXEC::transform_completion_signatures<
130 ::STDEXEC::__concat_completion_signatures_t<::STDEXEC::completion_signatures_of_t<Senders, Env...>...>,
131 ::STDEXEC::completion_signatures<>,
136template <
typename Receiver,
typename... Senders>
149 template <
typename... Args>
151 template <
typename... Args>
160 template <
typename S>
170 return outstanding_.fetch_sub(1, std::memory_order_acq_rel) == 1;
178 [&](
auto&... states)
noexcept {
179 if (
stored_.load(std::memory_order_relaxed)) {
185 const auto impl = [&](
auto&
state)
noexcept {
186 if (
state.connect_rollback(rollback_receiver_type_{{*this}})) {
191 (states.start_rollback(), ...);
194 ::STDEXEC::set_value(std::move(
r_), ::STDEXEC::when_all(std::move(states).complete()...));
200 template <
typename... Args>
201 constexpr void fail_(Args&&... args)
noexcept {
202 if (!
stored_.exchange(
true, std::memory_order_relaxed)) {
214 explicit constexpr state(Receiver r, Senders&&... senders)
215 noexcept((std::is_nothrow_constructible_v<state_type_<Senders>, Senders, receiver_type_> && ...))
219 [&]()
noexcept(std::is_nothrow_constructible_v<
state_type_<Senders>, Senders, receiver_type_>) {
225 std::apply([](
auto&&... states)
noexcept { (states.start(), ...); },
states_);
229template <
typename Receiver,
typename... Senders>
231 return ::STDEXEC::get_env(
self_.
r_);
234template <
typename Receiver,
typename... Senders>
239template <
typename Receiver,
typename... Senders>
240template <
typename... Args>
242 self_.fail_(::STDEXEC::set_error, (Args&&) args...);
245template <
typename Receiver,
typename... Senders>
246template <
typename... Args>
248 self_.fail_(::STDEXEC::set_stopped, (Args&&) args...);
251template <
typename Receiver,
typename... Senders>
253 self_.rollback_complete_();
256template <
typename... Env>
259template <
typename Env>
261 template <
typename... Children>
262 using __f = ::STDEXEC::transform_completion_signatures<
263 ::STDEXEC::completion_signatures<::STDEXEC::set_value_t(
264 exit_sender_t<::exec::exit_scope_sender_of_t<Children, Env>...>)>,
272template <
typename Receiver>
274 template <
typename... Children>
278template <
typename Receiver>
280 template <
typename... Children>
281 using __f = std::is_nothrow_constructible<
state<Receiver, Children...>, Receiver, Children...>;
284class impl :
public ::STDEXEC::__sexpr_defaults {
285 template <
typename Sender,
typename... Env>
288 template <
typename Sender,
typename... Env>
290 if constexpr (::STDEXEC::__minvocable_q<
completions_, Sender, Env...>) {
292 }
else if constexpr (
sizeof...(Env) == 0) {
293 return STDEXEC::__throw_dependent_sender_error<Sender>();
295 return ::STDEXEC::__throw_compile_time_error<
297 ::STDEXEC::_WITH_SENDER_<Sender>
302 static constexpr auto __connect = []<
typename Sender,
typename Receiver>(Sender&& sender, Receiver r)
noexcept(
304 -> ::STDEXEC::__children_of<Sender, connect_result<Receiver>> {
305 return ::STDEXEC::__apply(
306 [&](
auto&&,
auto&&,
auto&&... children)
noexcept(
308 return ::STDEXEC::__children_of<Sender, connect_result<Receiver>>(
309 (Receiver&&) r, (
decltype(children)&&) children...);
325struct __sexpr_impl<::exec::enter_scopes_t> : ::exec::detail::enter_scopes::impl { };
std::variant< operation_state_type_, exit_scope_sender_type_, rollback_operation_state_type_ > storage_
constexpr exit_scope_sender_type_ && complete() &&noexcept
::stdexec::connect_result_t< exit_scope_sender_type_, RollbackReceiver > rollback_operation_state_type_
constexpr bool connect_rollback(RollbackReceiver r) &noexcept
constexpr void start() &noexcept
static constexpr bool nothrow_constructible_
constexpr enter_scope_sender_state(Sender &&sender, Receiver r) noexcept(nothrow_constructible_)
::stdexec::connect_result_t< Sender, receiver_type_ > operation_state_type_
constexpr void start_rollback() &noexcept
::exec::exit_scope_sender_of_t< Sender, env_type_ > exit_scope_sender_type_
::stdexec::env_of_t< Receiver > env_type_
::stdexec::__children_of< Sender, completions< Env... > > completions_
static constexpr auto __connect
static consteval auto __get_completion_signatures()
constexpr state(Receiver r, Senders &&... senders) noexcept((std::is_nothrow_constructible_v< state_type_< Senders >, Senders, receiver_type_ > &&...))
storage_for_completion_signatures<::stdexec::env_of_t< Receiver > >::template __f< Senders... > storage_
constexpr void complete_() noexcept
constexpr void fail_(Args &&... args) noexcept
std::atomic< std::size_t > outstanding_
::stdexec::env_of_t< Receiver > env_type_
std::atomic< bool > stored_
enter_scope_sender_state< S, receiver_type_, rollback_receiver_type_ > state_type_
constexpr bool is_complete_() noexcept
constexpr void rollback_complete_() noexcept
std::tuple< state_type_< Senders >... > states_
constexpr void start() &noexcept
::stdexec::completion_signatures<> remove_set_value_t
decltype(::stdexec::when_all(std::declval< Senders >()...)) exit_sender_t
constexpr enter_scopes_t enter_scopes
detail::enter_scopes::t enter_scopes_t
::stdexec::transform_completion_signatures< ::stdexec::completion_signatures<::stdexec::set_value_t( exit_sender_t<::exec::exit_scope_sender_of_t< Children, Env >... >)>, typename storage_for_completion_signatures< Env >::template __f< Children... >::completion_signatures > __f
state< Receiver, Children... > __f
enter_scope_sender_state & self_
constexpr void set_value(exit_scope_sender_type_ sender) &&noexcept
std::is_nothrow_constructible< state< Receiver, Children... >, Receiver, Children... > __f
::stdexec::receiver_t receiver_concept
constexpr env_type_ get_env() const noexcept
constexpr void set_value() &&noexcept
constexpr void set_stopped(Args &&...) &&noexcept
constexpr void set_error(Args &&...) &&noexcept
constexpr void set_value() &&noexcept
::exec::storage_for_completion_signatures<::stdexec::transform_completion_signatures< ::stdexec::__concat_completion_signatures_t<::stdexec::completion_signatures_of_t< Senders, Env... >... >, ::stdexec::completion_signatures<>, remove_set_value_t > > __f
constexpr ::exec::enter_scope_sender auto operator()(Senders &&... senders) const noexcept((std::is_nothrow_constructible_v< std::remove_cvref_t< Senders >, Senders > &&...))
constexpr ::exec::enter_scope_sender auto operator()(Sender &&sender) const noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Sender >, Sender >)
constexpr ::exec::enter_scope_sender auto operator()() const noexcept