atomgalaxy / review-executor-sendrecv

A board for reviewing the executors proposal P0440
1 stars 0 forks source link

Reusable senders #7

Open RobertLeahy opened 4 years ago

RobertLeahy commented 4 years ago

§1.6.2 (description of a hypothetical algorithm retry) describes reuse of a sender:

The set_error member, on the other hand, reconstructs the operation state in-place by making another call to connect with the original sender and a new instance of the custom receiver.

Which suggests that senders should be reusable, and that therefore connect ought to be callable on lvalue senders. However under my understanding this is contradicted in the formulation of _then_sender in the immediately preceding section (§1.6.1) which requires that connect only be called on objects of that type which are rvalues:

template<receiver R>
  requires sender_to<S, _then_receiver<R, F>>
state_t<S, _then_receiver<R, F>> connect(R r) && {
    return ::connect((S&&)s_, _then_receiver<R, F>{(R&&)r, (F&&)f_});
}

then and retry aren't in P0443 but reading these sections left me wondering what the intention was.

tomaszkam commented 4 years ago

From my understanding of the paper, the sender concepts is meant to be used with the &.&& references, to indicate if the given scheduler is meant to be used once, or multiple times.

Note that the concept definition, remove_cvref is applied on S to check if it is move_constructible:

template<class S>
      concept sender =
        move_constructible<remove_cvref_t<S>> &&
        !requires {
          typename sender_traits<remove_cvref_t<S>>::__unspecialized; // exposition only
        };

So, in exmaple you have quouted, then checks sender_to<S, R>, which then checks if connect on S&&, R&& (r-values), i.e. looks if sender is one-shot. On the other hand retry checks sender_to<S&, _retry_receiver<_op<R>, R>>, i.e. l-value for sender (connected multiple times) and r-value for receiver (because the ops are called only once).

In conclusion, I believe that the intent of concepts allows to check both once/multi sender, by using:

kirkshoop commented 4 years ago

I believe that then() is expected to be transparent to this. In libunifex transform() has been made transparent (this uses tag_invoke to provide some of the benefits of deduced-this so that there is only one overload of connect) https://github.com/facebookexperimental/libunifex/blob/master/include/unifex/transform.hpp#L161-L174