|
2609 | 2609 | the implementation is allowed to omit
|
2610 | 2610 | the \tcode{exception_ptr} error completion signature from the set.
|
2611 | 2611 |
|
| 2612 | +\rSec3[exec.adapt.obj]{Closure objects} |
| 2613 | + |
| 2614 | +\pnum |
| 2615 | +A \defnadj{pipeable}{sender adaptor closure object} is a function object |
| 2616 | +that accepts one or more \tcode{sender} arguments and returns a \tcode{sender}. |
| 2617 | +For a pipeable sender adaptor closure object \tcode{c} and |
| 2618 | +an expression \tcode{sndr} |
| 2619 | +such that \tcode{decltype((sndr))} models \tcode{sender}, |
| 2620 | +the following expressions are equivalent and yield a \tcode{sender}: |
| 2621 | +\begin{codeblock} |
| 2622 | +c(sndr) |
| 2623 | +sndr | c |
| 2624 | +\end{codeblock} |
| 2625 | +Given an additional pipeable sender adaptor closure object \tcode{d}, |
| 2626 | +the expression \tcode{c | d} produces |
| 2627 | +another pipeable sender adaptor closure object \tcode{e}: |
| 2628 | + |
| 2629 | +\tcode{e} is a perfect forwarding call wrapper\iref{func.require} |
| 2630 | +with the following properties: |
| 2631 | +\begin{itemize} |
| 2632 | +\item |
| 2633 | +Its target object is an object \tcode{d2} of type \tcode{decltype(auto(d))} |
| 2634 | +direct-non-list-initialized with \tcode{d}. |
| 2635 | +\item |
| 2636 | +It has one bound argument entity, |
| 2637 | +an object \tcode{c2} of type \tcode{decltype(auto(c))} |
| 2638 | +direct-non-list-initialized with \tcode{c}. |
| 2639 | +\item |
| 2640 | +Its call pattern is \tcode{d2(c2(arg))}, |
| 2641 | +where arg is the argument used in a function call expression of \tcode{e}. |
| 2642 | +\end{itemize} |
| 2643 | +The expression \tcode{c | d} is well-formed if and only if |
| 2644 | +the initializations of the state entities\iref{func.def} of \tcode{e} |
| 2645 | +are all well-formed. |
| 2646 | + |
| 2647 | +\pnum |
| 2648 | +An object \tcode{t} of type \tcode{T} is |
| 2649 | +a pipeable sender adaptor closure object |
| 2650 | +if \tcode{T} models \tcode{\libconcept{derived_from}<sender_adaptor_closure<T>>}, |
| 2651 | +\tcode{T} has no other base classes |
| 2652 | +of type \tcode{sender_adaptor_closure<U>} for any other type \tcode{U}, and |
| 2653 | +\tcode{T} does not satisfy \tcode{sender}. |
| 2654 | + |
| 2655 | +\pnum |
| 2656 | +The template parameter \tcode{D} for sender_adaptor_closure can be |
| 2657 | +an incomplete type. |
| 2658 | +Before any expression of type \cv{} \tcode{D} appears as |
| 2659 | +an operand to the \tcode{|} operator, |
| 2660 | +\tcode{D} shall be complete and |
| 2661 | +model \tcode{\libconcept{derived_from}<sender_adaptor_closure<D>>}. |
| 2662 | +The behavior of an expression involving an object of type \cv{} \tcode{D} |
| 2663 | +as an operand to the \tcode{|} operator is undefined |
| 2664 | +if overload resolution selects a program-defined \tcode{operator|} function. |
| 2665 | + |
| 2666 | +\pnum |
| 2667 | +A \defnadj{pipeable}{sender adaptor object} is a customization point object |
| 2668 | +that accepts a \tcode{sender} as its first argument and |
| 2669 | +returns a \tcode{sender}. |
| 2670 | +If a pipeable sender adaptor object accepts only one argument, |
| 2671 | +then it is a pipeable sender adaptor closure object. |
| 2672 | + |
| 2673 | +\pnum |
| 2674 | +If a pipeable sender adaptor object adaptor accepts more than one argument, |
| 2675 | +then let \tcode{sndr} be an expression |
| 2676 | +such that \tcode{decltype((sndr))} models \libconcept{sender}, |
| 2677 | +let \tcode{args...} be arguments |
| 2678 | +such that \tcode{adaptor(sndr, args...)} is a well-formed expression |
| 2679 | +as specified below, and |
| 2680 | +let \tcode{BoundArgs} be a pack that denotes \tcode{decltype(auto(args))...}. |
| 2681 | +The expression \tcode{adaptor(args...)} produces |
| 2682 | +a pipeable sender adaptor closure object \tcode{f} |
| 2683 | +that is a perfect forwarding call wrapper with the following properties: |
| 2684 | +\begin{itemize} |
| 2685 | +\item |
| 2686 | +Its target object is a copy of adaptor. |
| 2687 | +\item |
| 2688 | +Its bound argument entities \tcode{bound_args} consist of |
| 2689 | +objects of types \tcode{BoundArgs...} direct-non-list-initialized with |
| 2690 | +\tcode{std::forward<decltype((args))>(args)...}, respectively. |
| 2691 | +\item |
| 2692 | +Its call pattern is \tcode{adaptor(rcvr, bound_args...)}, |
| 2693 | +where \tcode{rcvr} is |
| 2694 | +the argument used in a function call expression of \tcode{f}. |
| 2695 | +\end{itemize} |
| 2696 | +The expression \tcode{adaptor(args...)} is well-formed if and only if |
| 2697 | +the initializations of the bound argument entities of the result, |
| 2698 | +as specified above, are all well-formed. |
| 2699 | + |
| 2700 | +\rSec3[exec.starts.on]{\tcode{execution::starts_on}} |
| 2701 | + |
| 2702 | +\pnum |
| 2703 | +\tcode{starts_on} adapts an input sender into a sender |
| 2704 | +that will start on an execution agent belonging to |
| 2705 | +a particular scheduler's associated execution resource. |
| 2706 | + |
| 2707 | +\pnum |
| 2708 | +The name \tcode{starts_on} denotes a customization point object. |
| 2709 | +For subexpressions \tcode{sch} and \tcode{sndr}, |
| 2710 | +if \tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or |
| 2711 | +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, |
| 2712 | +\tcode{starts_on(sch, sndr)} is ill-formed. |
| 2713 | + |
| 2714 | +\pnum |
| 2715 | +Otherwise, |
| 2716 | +the expression \tcode{starts_on(sch, sndr)} is expression-equivalent to: |
| 2717 | +\begin{codeblock} |
| 2718 | +transform_sender( |
| 2719 | + @\exposid{query-or-default}@(get_domain, sch, default_domain()), |
| 2720 | + @\exposid{make-sender}@(starts_on, sch, sndr)) |
| 2721 | +\end{codeblock} |
| 2722 | +except that \tcode{sch} is evaluated only once. |
| 2723 | + |
| 2724 | +\pnum |
| 2725 | +Let \tcode{out_sndr} and \tcode{env} be subexpressions |
| 2726 | +such that \tcode{OutSndr} is \tcode{decltype((out_sndr))}. |
| 2727 | +If \tcode{\exposconcept{sender-for}<OutSndr, starts_on_t>} is \tcode{false}, |
| 2728 | +then the expressions \tcode{starts_on.transform_env(out_sndr, env)} and |
| 2729 | +\tcode{starts_on.transform_sender(out_sndr, env)} are ill-formed; otherwise |
| 2730 | +\begin{itemize} |
| 2731 | +\item |
| 2732 | +\tcode{starts_on.transform_env(out_sndr, env)} is equivalent to: |
| 2733 | +\begin{codeblock} |
| 2734 | +auto&& [_, sch, _] = out_sndr; |
| 2735 | +return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ENV}@(sch), @\exposid{FWD-ENV}@(env)); |
| 2736 | +\end{codeblock} |
| 2737 | +\item |
| 2738 | +\tcode{starts_on.transform_sender(out_sndr, env)} is equivalent to: |
| 2739 | +\begin{codeblock} |
| 2740 | +auto&& [_, sch, sndr] = out_sndr; |
| 2741 | +return let_value( |
| 2742 | + schedule(sch), |
| 2743 | + [sndr = std::forward_like<OutSndr>(sndr)]() mutable |
| 2744 | + noexcept(is_nothrow_move_constructible_v) { |
| 2745 | + return std::move(sndr); |
| 2746 | + }); |
| 2747 | +\end{codeblock} |
| 2748 | +\end{itemize} |
| 2749 | + |
| 2750 | +\pnum |
| 2751 | +Let \tcode{out_sndr} be a subexpression denoting |
| 2752 | +a sender returned from \tcode{starts_on(sch, sndr)} or one equal to such, and |
| 2753 | +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. |
| 2754 | +Let \tcode{out_rcvr} be a subexpression denoting a receiver |
| 2755 | +that has an environment of type \tcode{Env} |
| 2756 | +such that \tcode{\libconcept{sender_in}<OutSndr, Env>} is \tcode{true}. |
| 2757 | +Let \tcode{op} be an lvalue referring to the operation state |
| 2758 | +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. |
| 2759 | +Calling \tcode{start(op)} shall start \tcode{sndr} |
| 2760 | +on an execution agent of the associated execution resource of \tcode{sch}. |
| 2761 | +If scheduling onto \tcode{sch} fails, |
| 2762 | +an error completion on \tcode{out_rcvr} shall be executed |
| 2763 | +on an unspecified execution agent. |
| 2764 | + |
| 2765 | +\rSec3[exec.continues.on]{\tcode{execution::continues_on}} |
| 2766 | + |
| 2767 | +\pnum |
| 2768 | +\tcode{continues_on} adapts a sender into one |
| 2769 | +that completes on the specified scheduler. |
| 2770 | + |
| 2771 | +\pnum |
| 2772 | +The name \tcode{continues_on} denotes a pipeable sender adaptor object. |
| 2773 | +For subexpressions \tcode{sch} and \tcode{sndr}, |
| 2774 | +if \tcode{decltype((sch))} does not satisfy \libconcept{scheduler}, or |
| 2775 | +\tcode{decltype((sndr))} does not satisfy \libconcept{sender}, |
| 2776 | +\tcode{continues_on(sndr, sch)} is ill-formed. |
| 2777 | + |
| 2778 | +\pnum |
| 2779 | +Otherwise, |
| 2780 | +the expression \tcode{continues_on(sndr, sch)} is expression-equivalent to: |
| 2781 | +\begin{codeblock} |
| 2782 | +transform_sender(@\exposid{get-domain-early}@(sndr), @\exposid{make-sender}@(continues_on, sch, sndr)) |
| 2783 | +\end{codeblock} |
| 2784 | +except that \tcode{sndr} is evaluated only once. |
| 2785 | + |
| 2786 | +\pnum |
| 2787 | +The exposition-only class template \exposid{impls-for} |
| 2788 | +is specialized for \tcode{continues_on_t} as follows: |
| 2789 | +\begin{codeblock} |
| 2790 | +namespace std::execution { |
| 2791 | + template<> |
| 2792 | + struct @\exposid{impls-for}@<continues_on_t> : @\exposid{default-impls}@ { |
| 2793 | + static constexpr auto get_attrs = |
| 2794 | + [](const auto& data, const auto& child) noexcept -> decltype(auto) { |
| 2795 | + return @\exposid{JOIN-ENV}@(@\exposid{SCHED-ATTRS}@(data), @\exposid{FWD-ENV}@(get_env(child))); |
| 2796 | + }; |
| 2797 | + }; |
| 2798 | +} |
| 2799 | +\end{codeblock} |
| 2800 | + |
| 2801 | +\pnum |
| 2802 | +Let \tcode{sndr} and \tcode{env} be subexpressions |
| 2803 | +such that \tcode{Sndr} is \tcode{decltype((sndr))}. |
| 2804 | +If \tcode{\exposconcept{sender-for}<Sndr, continues_on_t>} is \tcode{false}, |
| 2805 | +then |
| 2806 | +the expression \tcode{continues_on.transform_sender(sndr, env)} is ill-formed; |
| 2807 | +otherwise, it is equal to: |
| 2808 | +\begin{codeblock} |
| 2809 | +auto [_, data, child] = sndr; |
| 2810 | +return schedule_from(std::move(data), std::move(child)); |
| 2811 | +\end{codeblock} |
| 2812 | +\begin{note} |
| 2813 | +This causes the \tcode{continues_on(sndr, sch)} sender to become |
| 2814 | +\tcode{schedule_from(sch, sndr)} when it is connected with a receiver |
| 2815 | +whose execution domain does not customize \tcode{continues_on}. |
| 2816 | +\end{note} |
| 2817 | + |
| 2818 | +\pnum |
| 2819 | +Let \tcode{out_sndr} be a subexpression denoting |
| 2820 | +a sender returned from \tcode{continues_on(sndr, sch)} or one equal to such, and |
| 2821 | +let \tcode{OutSndr} be the type \tcode{decltype((out_sndr))}. |
| 2822 | +Let \tcode{out_rcvr} be a subexpression denoting a receiver |
| 2823 | +that has an environment of type \tcode{Env} |
| 2824 | +such that \tcode{\libconcept{sender_in}<OutSndr, Env>} is \tcode{true}. |
| 2825 | +Let \tcode{op} be an lvalue referring to the operation state |
| 2826 | +that results from connecting \tcode{out_sndr} with \tcode{out_rcvr}. |
| 2827 | +Calling \tcode{start(op)} shall |
| 2828 | +start \tcode{sndr} on the current execution agent and |
| 2829 | +execute completion operations on \tcode{out_rcvr} |
| 2830 | +on an execution agent of the execution resource associated with \tcode{sch}. |
| 2831 | +If scheduling onto \tcode{sch} fails, |
| 2832 | +an error completion on \tcode{out_rcvr} shall be executed |
| 2833 | +on an unspecified execution agent. |
| 2834 | + |
| 2835 | +\rSec3[exec.schedule.from]{\tcode{execution::schedule_from}} |
| 2836 | + |
2612 | 2837 | \rSec1[exec.util]{Sender/receiver utilities}
|
2613 | 2838 |
|
2614 | 2839 |
|
|
0 commit comments