|
2834 | 2834 |
|
2835 | 2835 | \rSec3[exec.schedule.from]{\tcode{execution::schedule_from}}
|
2836 | 2836 |
|
| 2837 | +\pnum |
| 2838 | +\tcode{schedule_from} schedules work dependent on the completion of a sender |
| 2839 | +onto a scheduler's associated execution resource. |
| 2840 | +\begin{note} |
| 2841 | +\tcode{schedule_from} is not meant to be used in user code; |
| 2842 | +it is used in the implementation of \tcode{continues_on}. |
| 2843 | +\end{note} |
| 2844 | + |
| 2845 | +\pnum |
| 2846 | +The name \tcode{schedule_from} denotes a customization point object. |
| 2847 | +For some subexpressions \tcode{sch} and \tcode{sndr}, |
| 2848 | +let \tcode{Sch} be \tcode{decltype((sch))} and |
| 2849 | +\tcode{Sndr} be \tcode{decltype((sndr))}. |
| 2850 | +If \tcode{Sch} does not satisfy \libconcept{scheduler}, or |
| 2851 | +\tcode{Sndr} does not satisfy \libconcept{sender}, |
| 2852 | +\tcode{schedule_from(sch, sndr)} is ill-formed. |
| 2853 | + |
| 2854 | +\pnum |
| 2855 | +Otherwise, |
| 2856 | +the expression \tcode{schedule_from(sch, sndr)} is expression-equivalent to: |
| 2857 | +\begin{codeblock} |
| 2858 | +transform_sender( |
| 2859 | + @\exposid{query-or-default}@(get_domain, sch, default_domain()), |
| 2860 | + @\exposid{make-sender}@(schedule_from, sch, sndr)) |
| 2861 | +\end{codeblock} |
| 2862 | +except that \tcode{sch} is evaluated only once. |
| 2863 | + |
| 2864 | +\pnum |
| 2865 | +The exposition-only class template \exposid{impls-for}\iref{exec.snd.general} |
| 2866 | +is specialized for \tcode{schedule_from_t} as follows: |
| 2867 | +\begin{codeblock} |
| 2868 | +namespace std::execution { |
| 2869 | + template<> |
| 2870 | + struct @\exposid{impls-for}@<schedule_from_t> : @\exposid{default-impls}@ { |
| 2871 | + static constexpr auto @\exposid{get-attrs}@ = @\seebelow@; |
| 2872 | + static constexpr auto @\exposid{get-state}@ = @\seebelow@; |
| 2873 | + static constexpr auto @\exposid{complete}@ = @\seebelow@; |
| 2874 | + }; |
| 2875 | +} |
| 2876 | +\end{codeblock} |
| 2877 | + |
| 2878 | +\pnum |
| 2879 | +The member \tcode{\exposid{impls-for}<schedule_from_t>::\exposid{get-attrs}} |
| 2880 | +is initialized with a callable object equivalent to the following lambda: |
| 2881 | +\begin{codeblock} |
| 2882 | +[](const auto& data, const auto& child) noexcept -> decltype(auto) { |
| 2883 | + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); |
| 2884 | +} |
| 2885 | +\end{codeblock} |
| 2886 | + |
| 2887 | +\pnum |
| 2888 | +The member \tcode{\exposid{impls-for}<schedule_from_t>::\exposid{get-state}} |
| 2889 | +is initialized with a callable object equivalent to the following lambda: |
| 2890 | +\begin{codeblock} |
| 2891 | +[]<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept(see below) |
| 2892 | + requires @\libconcept{sender_in}@<@\exposid{child-type}@<Sndr>, env_of_t<Rcvr>> { |
| 2893 | + |
| 2894 | + auto& [_, sch, child] = sndr; |
| 2895 | + |
| 2896 | + using sched_t = decltype(auto(sch)); |
| 2897 | + using variant_t = @\seebelow@; |
| 2898 | + using receiver_t = @\seebelow@; |
| 2899 | + using operation_t = connect_result_t<schedule_result_t<sched_t>, receiver_t>; |
| 2900 | + constexpr bool nothrow = noexcept(connect(schedule(sch), receiver_t{nullptr})); |
| 2901 | + |
| 2902 | + struct @\exposid{state-type}@ { |
| 2903 | + Rcvr& @\exposid{rcvr}@; // \expos |
| 2904 | + variant_t @\exposid{async-result}@; // \expos |
| 2905 | + operation_t @\exposid{op-state}@; // \expos |
| 2906 | + |
| 2907 | + explicit @\exposid{state-type}@(sched_t sch, Rcvr& rcvr) noexcept(nothrow) |
| 2908 | + : @\exposid{rcvr}@(rcvr), @\exposid{op-state}@(connect(schedule(sch), receiver_t{this})) {} |
| 2909 | + }; |
| 2910 | + |
| 2911 | + return @\exposid{state-type}@{sch, rcvr}; |
| 2912 | +} |
| 2913 | +\end{codeblock} |
| 2914 | + |
| 2915 | +\pnum |
| 2916 | +Objects of the local class \exposid{state-type} can be used |
| 2917 | +to initialize a structured binding. |
| 2918 | + |
| 2919 | +\pnum |
| 2920 | +Let \tcode{Sigs} be |
| 2921 | +a pack of the arguments to the \tcode{completion_signatures} specialization |
| 2922 | +named by \tcode{completion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>}. |
| 2923 | +Let \exposid{as-tuple} be an alias template |
| 2924 | +that transforms a completion signature \tcode{Tag(Args...)} into |
| 2925 | +the tuple specialization \tcode{decayed-tuple<Tag, Args...>}. |
| 2926 | +Then \tcode{variant_t} denotes |
| 2927 | +the type \tcode{variant<monostate, \exposid{as-tuple}<Sigs>...>}, |
| 2928 | +except with duplicate types removed. |
| 2929 | + |
| 2930 | +\pnum |
| 2931 | +\tcode{receiver_t} is an alias for the following exposition-only class: |
| 2932 | +\begin{codeblock} |
| 2933 | +namespace std::execution { |
| 2934 | + struct @\exposid{receiver-type}@ { |
| 2935 | + using receiver_concept = receiver_t; |
| 2936 | + @\exposid{state-type}@* @\exposid{state}@; // exposition only |
| 2937 | + |
| 2938 | + void set_value() && noexcept { |
| 2939 | + visit( |
| 2940 | + [this]<class Tuple>(Tuple& result) noexcept -> void { |
| 2941 | + if constexpr (!@\libconcept{same_as}@<monostate, Tuple>) { |
| 2942 | + auto& [tag, ...args] = result; |
| 2943 | + tag(std::move(@\exposid{state}@->@\exposid{rcvr}@), std::move(args)...); |
| 2944 | + } |
| 2945 | + }, |
| 2946 | + @\exposid{state}@->@\exposid{async-result}@); |
| 2947 | + } |
| 2948 | + |
| 2949 | + template<class Error> |
| 2950 | + void set_error(Error&& err) && noexcept { |
| 2951 | + execution::set_error(std::move(@\exposid{state}@->@\exposid{rcvr}@), std::forward<Error>(err)); |
| 2952 | + } |
| 2953 | + |
| 2954 | + void set_stopped() && noexcept { |
| 2955 | + execution::set_stopped(std::move(@\exposid{state}@->@\exposid{rcvr}@)); |
| 2956 | + } |
| 2957 | + |
| 2958 | + decltype(auto) get_env() const noexcept { |
| 2959 | + return @\exposid{FWD-ENV}@(execution::get_env(@\exposid{state}@->@\exposid{rcvr}@)); |
| 2960 | + } |
| 2961 | + }; |
| 2962 | +} |
| 2963 | +\end{codeblock} |
| 2964 | + |
| 2965 | +\pnum |
| 2966 | +The expression in the \tcode{noexcept} clause of the lambda is \tcode{true} |
| 2967 | +if the construction of the returned \exposid{state-type} object |
| 2968 | +is not potentially throwing; |
| 2969 | +otherwise, \tcode{false}. |
| 2970 | + |
| 2971 | +\pnum |
| 2972 | +The member \tcode{\exposid{impls-for}<schedule_from_t>::\exposid{complete}} |
| 2973 | +is initialized with a callable object equivalent to the following lambda: |
| 2974 | +\begin{codeblock} |
| 2975 | +[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { |
| 2976 | + using result_t = @\exposid{decayed-tuple}@<Tag, Args...>; |
| 2977 | + constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>; |
| 2978 | + |
| 2979 | + @\exposid{TRY-EVAL}@(rcvr, [&]() noexcept(nothrow) { |
| 2980 | + state.@\exposid{async-result}@.template emplace<result_t>(Tag(), std::forward<Args>(args)...); |
| 2981 | + }()); |
| 2982 | + |
| 2983 | + if (state.@\exposid{async-result}@.valueless_by_exception()) |
| 2984 | + return; |
| 2985 | + if (state.@\exposid{async-result}@.index() == 0) |
| 2986 | + return; |
| 2987 | + |
| 2988 | + start(state.@\exposid{op-state}@); |
| 2989 | +}; |
| 2990 | +\end{codeblock} |
| 2991 | + |
| 2992 | +\pnum |
| 2993 | +Let \tcode{out_sndr} be a subexpression denoting |
| 2994 | +a sender returned from \tcode{schedule_from(sch, sndr)} or one equal to such, |
| 2995 | +and let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. |
| 2996 | +Let \tcode{out_rcvr} be a subexpression denoting a receiver |
| 2997 | +that has an environment of type \tcode{Env} |
| 2998 | +such that \tcode{\libconcept{sender_in}<OutSndr, Env>} is \tcode{true}. |
| 2999 | +Let \tcode{op} be an lvalue referring to the operation state |
| 3000 | +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. |
| 3001 | +Calling \tcode{start(op)} shall |
| 3002 | +start \tcode{sndr} on the current execution agent and |
| 3003 | +execute completion operations on \tcode{out_rcvr} |
| 3004 | +on an execution agent of the execution resource associated with \tcode{sch}. |
| 3005 | +If scheduling onto \tcode{sch} fails, |
| 3006 | +an error completion on \tcode{out_rcvr} shall be executed |
| 3007 | +on an unspecified execution agent. |
| 3008 | + |
2837 | 3009 | \rSec1[exec.util]{Sender/receiver utilities}
|
2838 | 3010 |
|
2839 | 3011 |
|
|
0 commit comments