|
629 | 629 | struct @\libglobal{let_error_t}@ { @\unspec@ };
|
630 | 630 | struct @\libglobal{let_stopped_t}@ { @\unspec@ };
|
631 | 631 | struct @\libglobal{bulk_t}@ { @\unspec@ };
|
632 |
| - struct @\libglobal{split_t}@ { @\unspec@ }; |
633 | 632 | struct @\libglobal{when_all_t}@ { @\unspec@ };
|
634 | 633 | struct @\libglobal{when_all_with_variant_t}@ { @\unspec@ };
|
635 | 634 | struct @\libglobal{into_variant_t}@ { @\unspec@ };
|
|
647 | 646 | inline constexpr let_error_t @\libglobal{let_error}@{};
|
648 | 647 | inline constexpr let_stopped_t @\libglobal{let_stopped}@{};
|
649 | 648 | inline constexpr bulk_t @\libglobal{bulk}@{};
|
650 |
| - inline constexpr split_t @\libglobal{split}@{}; |
651 | 649 | inline constexpr when_all_t @\libglobal{when_all}@{};
|
652 | 650 | inline constexpr when_all_with_variant_t @\libglobal{when_all_with_variant}@{};
|
653 | 651 | inline constexpr into_variant_t @\libglobal{into_variant}@{};
|
|
3695 | 3693 | propagates all completion operations sent by \tcode{sndr}.
|
3696 | 3694 | \end{itemize}
|
3697 | 3695 |
|
3698 |
| -\rSec3[exec.split]{\tcode{execution::split}} |
3699 |
| - |
3700 |
| -\pnum |
3701 |
| -\tcode{split} adapts an arbitrary sender |
3702 |
| -into a sender that can be connected multiple times. |
3703 |
| - |
3704 |
| -\pnum |
3705 |
| -Let \exposid{split-env} be the type of an environment |
3706 |
| -such that, given an instance \tcode{env}, |
3707 |
| -the expression \tcode{get_stop_token(env)} is well-formed and |
3708 |
| -has type \tcode{inplace_stop_token.} |
3709 |
| - |
3710 |
| -\pnum |
3711 |
| -The name \tcode{split} denotes a pipeable sender adaptor object. |
3712 |
| -For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
3713 |
| -If \tcode{\libconcept{sender_in}<Sndr, \exposid{split-env}>} is \tcode{false}, |
3714 |
| -\tcode{split(sndr)} is ill-formed. |
3715 |
| - |
3716 |
| -\pnum |
3717 |
| -Otherwise, the expression \tcode{split(sndr)} is expression-equivalent to: |
3718 |
| -\begin{codeblock} |
3719 |
| -transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(split, {}, sndr)) |
3720 |
| -\end{codeblock} |
3721 |
| -except that \tcode{sndr} is evaluated only once. |
3722 |
| -\begin{note} |
3723 |
| -The default implementation of \tcode{transform_sender} |
3724 |
| -will have the effect of connecting the sender to a receiver. |
3725 |
| -It will return a sender with a different tag type. |
3726 |
| -\end{note} |
3727 |
| - |
3728 |
| -\pnum |
3729 |
| -Let \exposid{local-state} denote the following exposition-only class template: |
3730 |
| - |
3731 |
| -\begin{codeblock} |
3732 |
| -namespace std::execution { |
3733 |
| - struct @\exposid{local-state-base}@ { // \expos |
3734 |
| - virtual ~@\exposid{local-state-base}@() = default; |
3735 |
| - virtual void @\exposid{notify}@() noexcept = 0; // \expos |
3736 |
| - }; |
3737 |
| - |
3738 |
| - template<class Sndr, class Rcvr> |
3739 |
| - struct @\exposid{local-state}@ : @\exposid{local-state-base}@ { // \expos |
3740 |
| - using @\exposid{on-stop-callback}@ = // \expos |
3741 |
| - stop_callback_for_t<stop_token_of_t<env_of_t<Rcvr>>, @\exposid{on-stop-request}@>; |
3742 |
| - |
3743 |
| - @\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; |
3744 |
| - ~@\exposid{local-state}@(); |
3745 |
| - |
3746 |
| - void @\exposid{notify}@() noexcept override; |
3747 |
| - |
3748 |
| - private: |
3749 |
| - optional<@\exposid{on-stop-callback}@> @\exposid{on_stop}@; // \expos |
3750 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos |
3751 |
| - Rcvr* @\exposid{rcvr}@; // \expos |
3752 |
| - }; |
3753 |
| -} |
3754 |
| -\end{codeblock} |
3755 |
| - |
3756 |
| -\begin{itemdecl} |
3757 |
| -@\exposid{local-state}@(Sndr&& sndr, Rcvr& rcvr) noexcept; |
3758 |
| -\end{itemdecl} |
3759 |
| - |
3760 |
| -\begin{itemdescr} |
3761 |
| -\pnum |
3762 |
| -\effects |
3763 |
| -Equivalent to: |
3764 |
| -\begin{codeblock} |
3765 |
| -auto& [_, data, _] = sndr; |
3766 |
| -this->@\exposid{sh_state}@ = data.sh_state.get(); |
3767 |
| -this->@\exposid{sh_state}@->@\exposid{inc-ref}@(); |
3768 |
| -this->@\exposid{rcvr}@ = addressof(rcvr); |
3769 |
| -\end{codeblock} |
3770 |
| -\end{itemdescr} |
3771 |
| - |
3772 |
| -\begin{itemdecl} |
3773 |
| -~@\exposid{local-state}@(); |
3774 |
| -\end{itemdecl} |
3775 |
| - |
3776 |
| -\begin{itemdescr} |
3777 |
| -\pnum |
3778 |
| -\effects |
3779 |
| -Equivalent to: |
3780 |
| -\begin{codeblock} |
3781 |
| -sh_state->@\exposid{dec-ref}@(); |
3782 |
| -\end{codeblock} |
3783 |
| -\end{itemdescr} |
3784 |
| - |
3785 |
| -\begin{itemdecl} |
3786 |
| -void @\exposid{notify}@() noexcept override; |
3787 |
| -\end{itemdecl} |
3788 |
| - |
3789 |
| -\begin{itemdescr} |
3790 |
| -\pnum |
3791 |
| -\effects |
3792 |
| -Equivalent to: |
3793 |
| -\begin{codeblock} |
3794 |
| -@\exposid{on_stop}@.reset(); |
3795 |
| -visit( |
3796 |
| - [this](const auto& tupl) noexcept -> void { |
3797 |
| - apply( |
3798 |
| - [this](auto tag, const auto&... args) noexcept -> void { |
3799 |
| - tag(std::move(*@\exposid{rcvr}@), args...); |
3800 |
| - }, |
3801 |
| - tupl); |
3802 |
| - }, |
3803 |
| - @\exposid{sh_state}@->result); |
3804 |
| -\end{codeblock} |
3805 |
| -\end{itemdescr} |
3806 |
| - |
3807 |
| -\pnum |
3808 |
| -Let \exposid{split-receiver} denote |
3809 |
| -the following exposition-only class template: |
3810 |
| -\begin{codeblock} |
3811 |
| -namespace std::execution { |
3812 |
| - template<class Sndr> |
3813 |
| - struct @\exposid{split-receiver}@ { // \expos |
3814 |
| - using receiver_concept = receiver_t; |
3815 |
| - |
3816 |
| - template<class Tag, class... Args> |
3817 |
| - void @\exposid{complete}@(Tag, Args&&... args) noexcept { // \expos |
3818 |
| - using tuple_t = @\exposid{decayed-tuple}@<Tag, Args...>; |
3819 |
| - try { |
3820 |
| - @\exposid{sh_state}@->result.template emplace<tuple_t>(Tag(), std::forward<Args>(args)...); |
3821 |
| - } catch (...) { |
3822 |
| - using tuple_t = tuple<set_error_t, exception_ptr>; |
3823 |
| - @\exposid{sh_state}@->result.template emplace<tuple_t>(set_error, current_exception()); |
3824 |
| - } |
3825 |
| - @\exposid{sh_state}@->notify(); |
3826 |
| - } |
3827 |
| - |
3828 |
| - template<class... Args> |
3829 |
| - void set_value(Args&&... args) && noexcept { |
3830 |
| - @\exposid{complete}@(execution::set_value, std::forward<Args>(args)...); |
3831 |
| - } |
3832 |
| - |
3833 |
| - template<class Error> |
3834 |
| - void set_error(Error&& err) && noexcept { |
3835 |
| - @\exposid{complete}@(execution::set_error, std::forward<Error>(err)); |
3836 |
| - } |
3837 |
| - |
3838 |
| - void set_stopped() && noexcept { |
3839 |
| - @\exposid{complete}@(execution::set_stopped); |
3840 |
| - } |
3841 |
| - |
3842 |
| - struct @\exposid{env}@ { // \expos |
3843 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh-state}@; // \expos |
3844 |
| - |
3845 |
| - inplace_stop_token query(get_stop_token_t) const noexcept { |
3846 |
| - return @\exposid{sh-state}@->stop_src.get_token(); |
3847 |
| - } |
3848 |
| - }; |
3849 |
| - |
3850 |
| - @\exposid{env}@ get_env() const noexcept { |
3851 |
| - return @\exposid{env}@{@\exposid{sh_state}@}; |
3852 |
| - } |
3853 |
| - |
3854 |
| - @\exposid{shared-state}@<Sndr>* @\exposid{sh_state}@; // \expos |
3855 |
| - }; |
3856 |
| -} |
3857 |
| -\end{codeblock} |
3858 |
| - |
3859 |
| -\pnum |
3860 |
| -Let \exposid{shared-state} denote the following exposition-only class template: |
3861 |
| -\begin{codeblock} |
3862 |
| -namespace std::execution { |
3863 |
| - template<class Sndr> |
3864 |
| - struct @\exposid{shared-state}@ { |
3865 |
| - using @\exposid{variant-type}@ = @\seebelow@; // \expos |
3866 |
| - using @\exposid{state-list-type}@ = @\seebelow@; // \expos |
3867 |
| - |
3868 |
| - explicit @\exposid{shared-state}@(Sndr&& sndr); |
3869 |
| - |
3870 |
| - void @\exposid{start-op}@() noexcept; // \expos |
3871 |
| - void @\exposid{notify}@() noexcept; // \expos |
3872 |
| - void @\exposid{inc-ref}@() noexcept; // \expos |
3873 |
| - void @\exposid{dec-ref}@() noexcept; // \expos |
3874 |
| - |
3875 |
| - inplace_stop_source @\exposid{stop_src}@{}; // \expos |
3876 |
| - @\exposid{variant-type}@ @\exposid{result}@{}; // \expos |
3877 |
| - @\exposid{state-list-type}@ @\exposid{waiting_states}@; // \expos |
3878 |
| - atomic<bool> @\exposid{completed}@{false}; // \expos |
3879 |
| - atomic<size_t> @\exposid{ref_count}@{1}; // \expos |
3880 |
| - connect_result_t<Sndr, @\exposid{split-receiver}@<Sndr>> @\exposid{op_state}@; // \expos |
3881 |
| - }; |
3882 |
| -} |
3883 |
| -\end{codeblock} |
3884 |
| - |
3885 |
| -\pnum |
3886 |
| -Let \tcode{Sigs} be a pack of the arguments |
3887 |
| -to the \tcode{completion_signatures} specialization |
3888 |
| -named by \tcode{completion_signatures_of_t<Sndr>}. |
3889 |
| -For type \tcode{Tag} and pack \tcode{Args}, |
3890 |
| -let \exposid{as-tuple} be an alias template |
3891 |
| -such that \tcode{\exposid{as-tuple}<Tag(Args...)>} denotes |
3892 |
| -the type \tcode{\exposid{decayed-tuple}<Tag, Args...>}. |
3893 |
| -Then \exposid{variant-type} denotes the type |
3894 |
| -\begin{codeblock} |
3895 |
| -variant<tuple<set_stopped_t>, tuple<set_error_t, exception_ptr>, @\exposid{as-tuple}@<Sigs>...> |
3896 |
| -\end{codeblock} |
3897 |
| -but with duplicate types removed. |
3898 |
| - |
3899 |
| -\pnum |
3900 |
| -Let \exposid{state-list-type} be a type |
3901 |
| -that stores a list of pointers to \exposid{local-state-base} objects and |
3902 |
| -that permits atomic insertion. |
3903 |
| - |
3904 |
| -\begin{itemdecl} |
3905 |
| -explicit @\exposid{shared-state}@(Sndr&& sndr); |
3906 |
| -\end{itemdecl} |
3907 |
| - |
3908 |
| -\begin{itemdescr} |
3909 |
| -\pnum |
3910 |
| -\effects |
3911 |
| -Initializes \exposid{op_state} with the result of |
3912 |
| -\tcode{connect(std::forward<Sndr>(sndr), \exposid{split-re\-ceiver}\{this\})}. |
3913 |
| - |
3914 |
| -\pnum |
3915 |
| -\ensures |
3916 |
| -\exposid{waiting_states} is empty, and \exposid{completed} is \tcode{false}. |
3917 |
| -\end{itemdescr} |
3918 |
| - |
3919 |
| -\begin{itemdecl} |
3920 |
| -void @\exposid{start-op}@() noexcept; |
3921 |
| -\end{itemdecl} |
3922 |
| - |
3923 |
| -\begin{itemdescr} |
3924 |
| -\pnum |
3925 |
| -\effects |
3926 |
| -Evaluates \tcode{\exposid{inc-ref}()}. |
3927 |
| -If \tcode{stop_src.stop_requested()} is \tcode{true}, |
3928 |
| -evaluates \tcode{\exposid{notify}()}; |
3929 |
| -otherwise, evaluates \tcode{start(\exposid{op_state})}. |
3930 |
| -\end{itemdescr} |
3931 |
| - |
3932 |
| -\begin{itemdecl} |
3933 |
| -void @\exposid{notify}@() noexcept; |
3934 |
| -\end{itemdecl} |
3935 |
| - |
3936 |
| -\begin{itemdescr} |
3937 |
| -\pnum |
3938 |
| -\effects |
3939 |
| -Atomically does the following: |
3940 |
| -\begin{itemize} |
3941 |
| -\item |
3942 |
| -Sets \tcode{completed} to \tcode{true}, and |
3943 |
| -\item |
3944 |
| -Exchanges \tcode{waiting_states} with an empty list, |
3945 |
| -storing the old value in a local \tcode{prior_states}. |
3946 |
| -\end{itemize} |
3947 |
| -Then, for each pointer \tcode{p} in \tcode{prior_states}, |
3948 |
| -evaluates \tcode{p->\exposid{notify}()}. |
3949 |
| -Finally, evaluates \tcode{\exposid{dec-ref}()}. |
3950 |
| -\end{itemdescr} |
3951 |
| - |
3952 |
| -\begin{itemdecl} |
3953 |
| -void @\exposid{inc-ref}@() noexcept; |
3954 |
| -\end{itemdecl} |
3955 |
| - |
3956 |
| -\begin{itemdescr} |
3957 |
| -\pnum |
3958 |
| -\effects |
3959 |
| -Increments \exposid{ref_count}. |
3960 |
| -\end{itemdescr} |
3961 |
| - |
3962 |
| -\begin{itemdecl} |
3963 |
| -void @\exposid{dec-ref}@() noexcept; |
3964 |
| -\end{itemdecl} |
3965 |
| - |
3966 |
| -\begin{itemdescr} |
3967 |
| -\pnum |
3968 |
| -\effects |
3969 |
| -Decrements \exposid{ref_count}. |
3970 |
| -If the new value of \exposid{ref_count} is \tcode{0}, |
3971 |
| -calls \tcode{delete this}. |
3972 |
| - |
3973 |
| -\pnum |
3974 |
| -\sync |
3975 |
| -If an evaluation of \tcode{\exposid{dec-ref}()} does not |
3976 |
| -decrement the \tcode{ref_count} to \tcode{0} then |
3977 |
| -synchronizes with the evaluation of \tcode{dec-ref()} |
3978 |
| -that decrements \tcode{ref_count} to \tcode{0}. |
3979 |
| -\end{itemdescr} |
3980 |
| - |
3981 |
| -\pnum |
3982 |
| -Let \exposid{split-impl-tag} be an empty exposition-only class type. |
3983 |
| -Given an expression \tcode{sndr}, |
3984 |
| -the expression \tcode{split.transform_sender(sndr)} is equivalent to: |
3985 |
| -\begin{codeblock} |
3986 |
| -auto&& [tag, _, child] = sndr; |
3987 |
| -auto* sh_state = new @\exposid{shared-state}@{std::forward_like<decltype((sndr))>(child)}; |
3988 |
| -return @\exposid{make-sender}@(@\exposid{split-impl-tag}@(), @\exposid{shared-wrapper}@{sh_state, tag}); |
3989 |
| -\end{codeblock} |
3990 |
| -where \exposid{shared-wrapper} is an exposition-only class |
3991 |
| -that manages the reference count of the \exposid{shared-state} object |
3992 |
| -pointed to by sh_state. |
3993 |
| -\exposid{shared-wrapper} models \libconcept{copyable} |
3994 |
| -with move operations nulling out the moved-from object, |
3995 |
| -copy operations incrementing the reference count |
3996 |
| -by calling \tcode{sh_state->\exposid{inc-ref}()}, and |
3997 |
| -assignment operations performing a copy-and-swap operation. |
3998 |
| -The destructor has no effect if sh_state is null; |
3999 |
| -otherwise, it decrements the reference count |
4000 |
| -by evaluating \tcode{sh_state->\exposid{dec-ref}()}. |
4001 |
| - |
4002 |
| -\pnum |
4003 |
| -The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} |
4004 |
| -is specialized for \exposid{split-impl-tag} as follows: |
4005 |
| -\begin{codeblock} |
4006 |
| -namespace std::execution { |
4007 |
| - template<> |
4008 |
| - struct @\exposid{impls-for}@<@\exposid{split-impl-tag}@> : @\exposid{default-impls}@ { |
4009 |
| - static constexpr auto @\exposid{get-state}@ = @\seebelow@; |
4010 |
| - static constexpr auto @\exposid{start}@ = @\seebelow@; |
4011 |
| - }; |
4012 |
| -} |
4013 |
| -\end{codeblock} |
4014 |
| - |
4015 |
| -\pnum |
4016 |
| -The member |
4017 |
| -\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{get-state}} |
4018 |
| -is initialized with a callable object equivalent to |
4019 |
| -the following lambda expression: |
4020 |
| -\begin{codeblock} |
4021 |
| -[]<class Sndr>(Sndr&& sndr, auto& rcvr) noexcept { |
4022 |
| - return @\exposid{local-state}@{std::forward<Sndr>(sndr), rcvr}; |
4023 |
| -} |
4024 |
| -\end{codeblock} |
4025 |
| - |
4026 |
| -\pnum |
4027 |
| -The member |
4028 |
| -\tcode{\exposid{impls-for}<\exposid{split-impl-tag}>::\exposid{start}} |
4029 |
| -is initialized with a callable object |
4030 |
| -that has a function call operator equivalent to the following: |
4031 |
| -\begin{codeblock} |
4032 |
| -template<class Sndr, class Rcvr> |
4033 |
| -void operator()(@\exposid{local-state}@<Sndr, Rcvr>& state, Rcvr& rcvr) const noexcept; |
4034 |
| -\end{codeblock} |
4035 |
| - |
4036 |
| -\effects |
4037 |
| -If \tcode{state.\exposid{sh_state}->\exposid{completed}} is \tcode{true}, |
4038 |
| -evaluates \tcode{state.\exposid{notify}()} and returns. |
4039 |
| -Otherwise, does the following in order: |
4040 |
| -\begin{itemize} |
4041 |
| -\item |
4042 |
| -Evaluates |
4043 |
| -\begin{codeblock} |
4044 |
| -state.@\exposid{on_stop}@.emplace( |
4045 |
| - get_stop_token(get_env(rcvr)), |
4046 |
| - @\exposid{on-stop-request}@{state.@\exposid{sh_state}@->@\exposid{stop_src}@}); |
4047 |
| -\end{codeblock} |
4048 |
| -\item |
4049 |
| -Then atomically does the following: |
4050 |
| -\begin{itemize} |
4051 |
| -\item |
4052 |
| -Reads the value \tcode{c} of |
4053 |
| -\tcode{state.\exposid{sh_state}->\exposid{completed}}, and |
4054 |
| -\item |
4055 |
| -Inserts \tcode{addressof(state)} into |
4056 |
| -\tcode{state.\exposid{sh_state}->\exposid{waiting_states}} |
4057 |
| -if \tcode{c} is \tcode{false}. |
4058 |
| -\end{itemize} |
4059 |
| -\item |
4060 |
| -If \tcode{c} is \tcode{true}, |
4061 |
| -calls \tcode{state.\exposid{notify}()} and returns. |
4062 |
| -\item |
4063 |
| -Otherwise, |
4064 |
| -if \tcode{addressof(state)} is the first item added to |
4065 |
| -\tcode{state.\exposid{sh_state}->\exposid{waiting_states}}, |
4066 |
| -evaluates \tcode{state.\exposid{sh_state}->\exposid{start-op}()}. |
4067 |
| -\end{itemize} |
4068 |
| - |
4069 | 3696 | \rSec3[exec.when.all]{\tcode{execution::when_all}}
|
4070 | 3697 |
|
4071 | 3698 | \pnum
|
|
0 commit comments