Skip to content

Commit 968f1ab

Browse files
committed
fixup: add upto 34.9.11.10
1 parent c3dff2b commit 968f1ab

File tree

1 file changed

+369
-0
lines changed

1 file changed

+369
-0
lines changed

source/exec.tex

Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3574,6 +3574,375 @@
35743574
propagates all completion operations sent by \tcode{sndr}.
35753575
\end{itemize}
35763576

3577+
\rSec3[exec.split]{\tcode{execution::split}}
3578+
3579+
\pnum
3580+
\tcode{split} adapts an arbitrary sender
3581+
into a sender that can be connected multiple times.
3582+
3583+
\pnum
3584+
Let \exposid{split-env} be the type of an environment
3585+
such that, given an instance \tcode{env},
3586+
the expression \tcode{get_stop_token(env)} is well-formed and
3587+
has type \tcode{inplace_stop_token.}
3588+
3589+
\pnum
3590+
The name \tcode{split} denotes a pipeable sender adaptor object.
3591+
For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}.
3592+
If \tcode{\libconcept{sender_in}<Sndr, \exposid{split-env}>} is \tcode{false},
3593+
\tcode{split(sndr)} is ill-formed.
3594+
3595+
\pnum
3596+
Otherwise, the expression \tcode{split(sndr)} is expression-equivalent to:
3597+
\begin{codeblock}
3598+
transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(split, {}, sndr))
3599+
\end{codeblock}
3600+
except that \tcode{sndr} is evaluated only once.
3601+
\begin{note}
3602+
The default implementation of \tcode{transform_sender}
3603+
will have the effect of connecting the sender to a receiver.
3604+
It will return a sender with a different tag type.
3605+
\end{note}
3606+
3607+
\pnum
3608+
Let \exposid{local-state} denote the following exposition-only class template:
3609+
3610+
\begin{codeblock}
3611+
namespace std::execution {
3612+
struct @\exposid{local-state-base}@ { // \expos
3613+
virtual ~@\exposid{local-state-base}@() = default;
3614+
virtual void @\exposid{notify}@() noexcept = 0; // \expos
3615+
};
3616+
3617+
template<class Sndr, class Rcvr>
3618+
struct @\exposid{local-state}@ : @\exposid{local-state-base}@ { // \expos
3619+
using @\exposid{on-stop-callback}@ = // \expos
3620+
stop_callback_of_t<stop_token_of_t<env_of_t<Rcvr>>, @\exposid{on-stop-request}@>;
3621+
3622+
@\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept;
3623+
~@\exposid{local-state}@();
3624+
3625+
void @\exposid{notify}@() noexcept override;
3626+
3627+
private:
3628+
optional<@\exposid{on-stop-callback}@> @\exposid{on_stop}@; // \expos
3629+
@\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos
3630+
Rcvr* @\exposid{rcvr}@; // \expos
3631+
};
3632+
}
3633+
\end{codeblock}
3634+
3635+
\begin{itemdecl}
3636+
local-state(Sndr&& sndr, Rcvr& rcvr) noexcept;
3637+
\end{itemdecl}
3638+
3639+
\begin{itemdescr}
3640+
\pnum
3641+
\effects
3642+
Equivalent to:
3643+
\begin{codeblock}
3644+
auto& [_, data, _] = sndr;
3645+
this->@\exposid{sh_state}@ = data.sh_state.get();
3646+
this->@\exposid{sh_state}@->@\exposid{inc-ref}@();
3647+
this->@\exposid{rcvr}@ = addressof(rcvr);
3648+
\end{codeblock}
3649+
\end{itemdescr}
3650+
3651+
\begin{itemdecl}
3652+
~@\exposid{local-state}@();
3653+
\end{itemdecl}
3654+
3655+
\begin{itemdescr}
3656+
\pnum
3657+
\effects
3658+
Equivalent to:
3659+
\begin{codeblock}
3660+
sh_state->@\exposid{dec-ref}@();
3661+
\end{codeblock}
3662+
\end{itemdescr}
3663+
3664+
\begin{itemdecl}
3665+
void @\exposid{notify}@() noexcept override;
3666+
\end{itemdecl}
3667+
3668+
\begin{itemdescr}
3669+
\pnum
3670+
\effects
3671+
Equivalent to:
3672+
\begin{codeblock}
3673+
@\exposid{on_stop}@.reset();
3674+
visit(
3675+
[this](const auto& tupl) noexcept -> void {
3676+
apply(
3677+
[this](auto tag, const auto&... args) noexcept -> void {
3678+
tag(std::move(*@\exposid{rcvr}@), args...);
3679+
},
3680+
tupl);
3681+
},
3682+
@\exposid{sh_state}@->result);
3683+
\end{codeblock}
3684+
\end{itemdescr}
3685+
3686+
\pnum
3687+
Let \exposid{split-receiver} denote
3688+
the following exposition-only class template:
3689+
\begin{codeblock}
3690+
namespace std::execution {
3691+
template<class Sndr>
3692+
struct @\exposid{split-receiver}@ { // \expos
3693+
using receiver_concept = receiver_t;
3694+
3695+
template<class Tag, class... Args>
3696+
void @\exposid{complete}@(Tag, Args&&... args) noexcept { // \expos
3697+
using tuple_t = @\exposid{decayed-tuple}@<Tag, Args...>;
3698+
try {
3699+
@\exposid{sh_state}@->result.template emplace<tuple_t>(Tag(), std::forward<Args>(args)...);
3700+
} catch (...) {
3701+
using tuple_t = tuple<set_error_t, exception_ptr>;
3702+
@\exposid{sh_state}@->result.template emplace<tuple_t>(set_error, current_exception());
3703+
}
3704+
@\exposid{sh_state}@->notify();
3705+
}
3706+
3707+
template<class... Args>
3708+
void set_value(Args&&... args) && noexcept {
3709+
@\exposid{complete}@(execution::set_value, std::forward<Args>(args)...);
3710+
}
3711+
3712+
template<class Error>
3713+
void set_error(Error&& err) && noexcept {
3714+
@\exposid{complete}@(execution::set_error, std::forward<Error>(err));
3715+
}
3716+
3717+
void set_stopped() && noexcept {
3718+
@\exposid{complete}@(execution::set_stopped);
3719+
}
3720+
3721+
struct @\exposid{env}@ { // \expos
3722+
@\exposid{shared-state}@<Sndr>* @\exposid{sh-state}@; // \expos
3723+
3724+
inplace_stop_token query(get_stop_token_t) const noexcept {
3725+
return @\exposid{sh-state}@->stop_src.get_token();
3726+
}
3727+
};
3728+
3729+
@\exposid{env}@ get_env() const noexcept {
3730+
return @\exposid{env}@{@\exposid{sh_state}@};
3731+
}
3732+
3733+
@\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos
3734+
};
3735+
}
3736+
\end{codeblock}
3737+
3738+
\pnum
3739+
Let \exposid{shared-state} denote the following exposition-only class template:
3740+
\begin{codeblock}
3741+
namespace std::execution {
3742+
template<class Sndr>
3743+
struct @\exposid{shared-state}@ {
3744+
using @\exposid{variant-type}@ = @\seebelow@; // \expos
3745+
using @\exposid{state-list-type}@ = @\seebelow@; // \expos
3746+
3747+
explicit @\exposid{shared-state}@(Sndr&& sndr);
3748+
3749+
void @\exposid{start-op}@() noexcept; // \expos
3750+
void @\exposid{notify}@() noexcept; // \expos
3751+
void @\exposid{inc-ref}@() noexcept; // \expos
3752+
void @\exposid{dec-ref}@() noexcept; // \expos
3753+
3754+
inplace_stop_source @\exposid{stop_src}@{}; // \expos
3755+
@\exposid{variant-type}@ @\exposid{result}@{}; // \expos
3756+
@\exposid{state-list-type}@ @\exposid{waiting_states}@; // \expos
3757+
atomic<bool> @\exposid{completed}@{false}; // \expos
3758+
atomic<size_t> @\exposid{ref_count}@{1}; // \expos
3759+
connect_result_t<Sndr, @\exposid{split-receiver}@<Sndr>> @\exposid{op_state}@; // \expos
3760+
};
3761+
}
3762+
\end{codeblock}
3763+
3764+
\pnum
3765+
Let \tcode{Sigs} be a pack of the arguments
3766+
to the \tcode{completion_signatures} specialization
3767+
named by \tcode{completion_signatures_of_t<Sndr>}.
3768+
For type \tcode{Tag} and pack \tcode{Args},
3769+
let \exposid{as-tuple} be an alias template
3770+
such that \tcode{\exposid{as-tuple}<Tag(Args...)>} denotes
3771+
the type \tcode{\exposid{decayed-tuple}<Tag, Args...>}.
3772+
Then \exposid{variant-type} denotes the type
3773+
\tcode{variant<tuple<set_stopped_t>, tuple<set_error_t, exception_ptr>, \exposid{as-tuple}<Sigs>...>},
3774+
but with duplicate types removed.
3775+
3776+
\pnum
3777+
Let \exposid{state-list-type} be a type
3778+
that stores a list of pointers to \exposid{local-state-base} objects and
3779+
that permits atomic insertion.
3780+
3781+
\begin{itemdecl}
3782+
explicit @\exposid{shared-state}@(Sndr&& sndr);
3783+
\end{itemdecl}
3784+
3785+
\begin{itemdescr}
3786+
\pnum
3787+
\effects
3788+
Initializes \exposid{op_state} with the result of
3789+
\tcode{connect(std::forward<Sndr>(sndr), \exposid{split-receiver}\{this\})}.
3790+
3791+
\pnum
3792+
\ensures
3793+
\exposid{waiting_states} is empty, and \exposid{completed} is \tcode{false}.
3794+
\end{itemdescr}
3795+
3796+
\begin{itemdecl}
3797+
void @\exposid{start-op}@() noexcept;
3798+
\end{itemdecl}
3799+
3800+
\begin{itemdescr}
3801+
\pnum
3802+
\effects
3803+
Evaluates \tcode{\exposid{inc-ref}()}.
3804+
If \tcode{stop_src.stop_requested()} is \tcode{true},
3805+
evaluates \tcode{\exposid{notify}()};
3806+
otherwise, evaluates \tcode{start(\exposid{op_state})}.
3807+
\end{itemdescr}
3808+
3809+
\begin{itemdecl}
3810+
void @\exposid{notify}@() noexcept;
3811+
\end{itemdecl}
3812+
3813+
\begin{itemdescr}
3814+
\pnum
3815+
\effects
3816+
Atomically does the following:
3817+
\begin{itemize}
3818+
\item
3819+
Sets \tcode{completed} to \tcode{true}, and
3820+
\item
3821+
Exchanges \tcode{waiting_states} with an empty list,
3822+
storing the old value in a local \tcode{prior_states}.
3823+
\end{itemize}
3824+
Then, for each pointer \tcode{p} in \tcode{prior_states},
3825+
evaluates \tcode{p->\exposid{notify}()}.
3826+
Finally, evaluates \tcode{\exposid{dec-ref}()}.
3827+
\end{itemdescr}
3828+
3829+
\begin{itemdecl}
3830+
void @\exposid{inc-ref}@() noexcept;
3831+
\end{itemdecl}
3832+
3833+
\begin{itemdescr}
3834+
\pnum
3835+
\effects
3836+
Increments \exposid{ref_count}.
3837+
\end{itemdescr}
3838+
3839+
\begin{itemdecl}
3840+
void @\exposid{dec-ref}@() noexcept;
3841+
\end{itemdecl}
3842+
3843+
\begin{itemdescr}
3844+
\pnum
3845+
\effects
3846+
Decrements \exposid{ref_count}.
3847+
If the new value of \exposid{ref_count} is \tcode{0},
3848+
calls \tcode{delete this}.
3849+
3850+
\pnum
3851+
\sync
3852+
If an evaluation of \tcode{\exposid{dec-ref}()} does not
3853+
decrement the \tcode{ref_count} to \tcode{0} then
3854+
synchronizes with the evaluation of \tcode{dec-ref()}
3855+
that decrements \tcode{ref_count} to \tcode{0}.
3856+
\end{itemdescr}
3857+
3858+
\pnum
3859+
Let \exposid{split-impl-tag} be an empty exposition-only class type.
3860+
Given an expression \tcode{sndr},
3861+
the expression \tcode{split.transform_sender(sndr)} is equivalent to:
3862+
\begin{codeblock}
3863+
auto&& [tag, _, child] = sndr;
3864+
auto* sh_state = new @\exposid{shared-state}@{std::forward_like<decltype((sndr))>(child)};
3865+
return @\exposid{make-sender}@(@\exposid{split-impl-tag}@(), @\exposid{shared-wrapper}@{sh_state, tag});
3866+
\end{codeblock}
3867+
where \exposid{shared-wrapper} is an exposition-only class
3868+
that manages the reference count of the \exposid{shared-state} object
3869+
pointed to by sh_state.
3870+
\exposid{shared-wrapper} models copyable
3871+
with move operations nulling out the moved-from object,
3872+
copy operations incrementing the reference count
3873+
by calling \tcode{sh_state->\exposid{inc-ref}()}, and
3874+
assignment operations performing a copy-and-swap operation.
3875+
The destructor has no effect if sh_state is null;
3876+
otherwise, it decrements the reference count
3877+
by evaluating \tcode{sh_state->\exposid{dec-ref}()}.
3878+
3879+
\pnum
3880+
The exposition-only class template \exposid{impls-for}\iref{exec.snd.general}
3881+
is specialized for \exposid{split-impl-tag} as follows:
3882+
\begin{codeblock}
3883+
namespace std::execution {
3884+
template<>
3885+
struct @\exposid{impls-for}@<@\exposid{split-impl-tag}@> : @\exposid{default-impls}@ {
3886+
static constexpr auto @\exposid{get-state}@ = @\seebelow@;
3887+
static constexpr auto @\exposid{start}@ = @\seebelow@;
3888+
};
3889+
}
3890+
\end{codeblock}
3891+
3892+
\pnum
3893+
The member
3894+
\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{get-state}}
3895+
is initialized with a callable object equivalent to
3896+
the following lambda expression:
3897+
\begin{codeblock}
3898+
[]<class Sndr>(Sndr&& sndr, auto& rcvr) noexcept {
3899+
return @\exposid{local-state}@{std::forward<Sndr>(sndr), rcvr};
3900+
}
3901+
\end{codeblock}
3902+
3903+
\pnum
3904+
The member
3905+
\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{start}}
3906+
is initialized with a callable object
3907+
that has a function call operator equivalent to the following:
3908+
\begin{codeblock}
3909+
template<class Sndr, class Rcvr>
3910+
void operator()(local-state<Sndr, Rcvr>& state, Rcvr& rcvr) const noexcept;
3911+
\end{codeblock}
3912+
3913+
\effects
3914+
If \tcode{state.\exposid{sh_state}->\exposid{completed}} is \tcode{true},
3915+
evaluates \tcode{state.\exposid{notify}()} and returns.
3916+
Otherwise, does the following in order:
3917+
\begin{itemize}
3918+
\item
3919+
Evaluates
3920+
\begin{codeblock}
3921+
state.@\exposid{on_stop}@.emplace(
3922+
get_stop_token(get_env(rcvr)),
3923+
@\exposid{on-stop-request}@{state.@\exposid{sh_state}@->@\exposid{stop_src}@});
3924+
\end{codeblock}
3925+
\item
3926+
Then atomically does the following:
3927+
\begin{itemize}
3928+
\item
3929+
Reads the value \tcode{c} of
3930+
\tcode{state.\exposid{sh_state}->\exposid{completed}}, and
3931+
\item
3932+
Inserts \tcode{addressof(state)} into
3933+
\tcode{state.\exposid{sh_state}->\exposid{waiting_states}}
3934+
if \tcode{c} is \tcode{false}.
3935+
\end{itemize}
3936+
\item
3937+
If \tcode{c} is \tcode{true},
3938+
calls \tcode{state.\exposid{notify}()} and returns.
3939+
\item
3940+
Otherwise,
3941+
if \tcode{addressof(state)} is the first item added to
3942+
\tcode{state.\exposid{sh_state}->\exposid{waiting_states}},
3943+
evaluates \tcode{state.\exposid{sh_state}->\exposid{start-op}()}.
3944+
\end{itemize}
3945+
35773946
\rSec1[exec.util]{Sender/receiver utilities}
35783947

35793948

0 commit comments

Comments
 (0)