From 748a25443d8f0a20d221cef4252ed508e0248911 Mon Sep 17 00:00:00 2001 From: Lewis Baker Date: Thu, 22 Feb 2024 10:42:28 +1030 Subject: [PATCH 1/8] Fix typo in numbering of section 4 of exec.when.all --- execution.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution.bs b/execution.bs index 3337ab7..0677789 100644 --- a/execution.bs +++ b/execution.bs @@ -6907,7 +6907,7 @@ template<class Domain, class Tag, sender Sndr, class... Args> make-sender(when_all, {}, sndr0, ... sndrn-1)); -9. The exposition-only class template impls-for +4. The exposition-only class template impls-for ([exec.snd.general]) is specialized for `when_all_t` as follows:

From 777c8ce54f210109ebd2e1be6e57c1f66a42b455 Mon Sep 17 00:00:00 2001
From: Lewis Baker 
Date: Thu, 22 Feb 2024 10:48:42 +1030
Subject: [PATCH 2/8] Use "... with a callable object equivalent to the
 following lambda" instead of "... with a callable object equal to the
 following lambda".

As suggested during LWG review 2024-02-21
---
 execution.bs | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/execution.bs b/execution.bs
index 0677789..5869479 100644
--- a/execution.bs
+++ b/execution.bs
@@ -5237,7 +5237,7 @@ enum class forward_progress_guarantee {
             [dcl.struct.bind].
 
         5. The member default-impls::get-attrs is initialized
-            with a callable object equal to the following lambda:
+            with a callable object equivalent to the following lambda:
 
               
               [](const auto& data, const auto&... child) noexcept -> decltype(auto) {
@@ -5249,7 +5249,7 @@ enum class forward_progress_guarantee {
               
6. The member default-impls::get-env is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
               []<class Rcvr>(auto index, auto& state, const Rcvr& rcvr) noexcept
@@ -5259,7 +5259,7 @@ enum class forward_progress_guarantee {
               
7. The member default-impls::get-state is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
               []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept -> decltype(auto) {
@@ -5268,7 +5268,7 @@ enum class forward_progress_guarantee {
               
8. The member default-impls::start is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
               [](auto& state, auto& rcvr, auto&... ops) noexcept -> void {
@@ -5277,7 +5277,7 @@ enum class forward_progress_guarantee {
               
9. The member default-impls::complete is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
               []<class Index, class Rcvr, class Tag, class... Args>(
@@ -6145,7 +6145,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
         
1. The member impls-for<schedule_from_t>::get-attrs is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
           [](const auto& data, const auto& child) noexcept -> decltype(auto) {
@@ -6154,7 +6154,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
2. The member impls-for<schedule_from_t>::get-state is initialized - with a callable object equal to the following lambda: + with a callable object equivalent to the following lambda:
           []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr)
@@ -6215,7 +6215,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                 
3. The member impls-for<schedule_from_t>::complete - is initialized with a callable object equal to the following lambda: + is initialized with a callable object equivalent to the following lambda:
           []<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void {
@@ -6370,7 +6370,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
             
2. impls-for<tag_t<let-cpo>>::get-state is - is initialized with a callable object equal to the following: + is initialized with a callable object equivalent to the following:
             []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) requires see below {
@@ -6425,7 +6425,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
             
4. impls-for<tag_t<let-cpo>>::complete is - is initialized with a callable object equal to the following: + is initialized with a callable object equivalent to the following:
             []<class Tag, class... Args>
@@ -6490,7 +6490,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
         
1. The member impls-for<bulk_t>::complete is - initialized with a callable object equal to the following lambda: + initialized with a callable object equivalent to the following lambda:
           []<class Index, class State, class Rcvr, class Tag, class... Args>
@@ -6806,7 +6806,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
 
     1. The member
         impls-for<shared-impl-tag>::get-state
-        is initialized with a callable object equal to the following lambda
+        is initialized with a callable object equivalent to the following lambda
         expression:
 
           
@@ -6922,7 +6922,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
         
1. The member impls-for<when_all_t>::get-attrs - is initialized with a callable object equal to the following lambda + is initialized with a callable object equivalent to the following lambda expression:
@@ -6938,7 +6938,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
2. The member impls-for<when_all_t>::get-env - is initialized with a callable object equal to the following lambda + is initialized with a callable object equivalent to the following lambda expression:
@@ -6949,7 +6949,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
3. The member impls-for<when_all_t>::get-state - is initialized with a callable object equal to the following lambda + is initialized with a callable object equivalent to the following lambda expression:
@@ -7051,7 +7051,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
               3. Otherwise, calls `set_stopped(std::move(rcvr))`.
 
     4. The member impls-for<when_all_t>::start
-        is initialized with a callable object equal to the following lambda
+        is initialized with a callable object equivalent to the following lambda
         expression:
 
           
@@ -7069,7 +7069,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
4. The member impls-for<when_all_t>::complete - is initialized with a callable object equal to the following lambda + is initialized with a callable object equivalent to the following lambda expression:
@@ -7188,7 +7188,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
 
     1. The member
         impls-for<into_variant_t>::get-state is
-        initialized with a callable object equal to the following lambda:
+        initialized with a callable object equivalent to the following lambda:
 
           
           []<class Sndr, class Rcvr>(Sndr&& sndr, Rcvr& rcvr) noexcept
@@ -7198,7 +7198,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
2. The member impls-for<into_variant_t>::complete - is initialized with a callable object equal to the following lambda: + is initialized with a callable object equivalent to the following lambda:
           []<class State, class Rcvr, class Tag, class... Args>(

From b12c74dae7663cd8af254b2fbae9d15759b6dbef Mon Sep 17 00:00:00 2001
From: Lewis Baker 
Date: Thu, 22 Feb 2024 10:58:47 +1030
Subject: [PATCH 3/8] Use "evaluates" instead of "calls" in description of
 [exec.when.all] state::complete effects.

The  code blocks below are not functions and so cannot be "called".
---
 execution.bs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/execution.bs b/execution.bs
index 5869479..b052947 100644
--- a/execution.bs
+++ b/execution.bs
@@ -7022,7 +7022,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
               noexcept behaves as follows:
 
               1. If `disp` is equal to disposition::started,
-                  calls:
+                  evaluates:
 
                   
                   auto tie = []<class... T>(tuple<T...>& t) noexcept { return tuple<T&...>(t); };
@@ -7036,7 +7036,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                   
2. Otherwise, if `disp` is equal to - disposition::error, calls: + disposition::error, evaluates:
                   visit(
@@ -7048,7 +7048,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                     errors);
                   
- 3. Otherwise, calls `set_stopped(std::move(rcvr))`. + 3. Otherwise, evaluates `set_stopped(std::move(rcvr))`. 4. The member impls-for<when_all_t>::start is initialized with a callable object equivalent to the following lambda From 3d1ede61e2c6488c687a4bff4946fbdf87158872 Mon Sep 17 00:00:00 2001 From: Lewis Baker Date: Thu, 22 Feb 2024 11:01:43 +1030 Subject: [PATCH 4/8] Remove `if constexpr` from [exec.when.all] state::complete handling of `disposition::started` case. The if constexpr was guarding against the case where there is a zero-sized pack of optionals holding the values, however p2 already says that when_all is ill-formed if the number of child senders is zero. --- execution.bs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/execution.bs b/execution.bs index b052947..9ad0339 100644 --- a/execution.bs +++ b/execution.bs @@ -7029,8 +7029,7 @@ template<class Domain, class Tag, sender Sndr, class... Args> auto set = [&](auto&... t) noexcept { set_value(std::move(rcvr), std::move(t)...); }; apply( [&](auto&... opts) noexcept { - if constexpr (sizeof...(opts) != 0) - apply(set, tuple_cat(tie(*opts)...)); + apply(set, tuple_cat(tie(*opts)...)); }, values);
From 2ac9f0e57bde748e6aa6409edc266a06b4f4dbe6 Mon Sep 17 00:00:00 2001 From: Lewis Baker Date: Thu, 22 Feb 2024 11:29:03 +1030 Subject: [PATCH 5/8] Explicitly reset the on_stop stop-callback object before calling completion function in [exec.when.all] stae::complete effects. It was considered too subtle to be relying on the destruction order of the members declared in the exposition-only local `state` struct to guarantee that the stop-callback is destroyed before the stop-source which the execution of the stop-callback might access. It also wasn't clear whether the listed order of member declarations in the 'state' structure was considered normative or whether we wanted to give implementations flexibility to declare members in different orders. The alternative considered was to add a note, or possibly something normative that requires that the 'on_stop' member is declared after the 'stop_src' member so that during destruction of the operation-state the stop-callback is destroyed before the stop-source. --- execution.bs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/execution.bs b/execution.bs index 9ad0339..5939b1c 100644 --- a/execution.bs +++ b/execution.bs @@ -7027,6 +7027,8 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                   auto tie = []<class... T>(tuple<T...>& t) noexcept { return tuple<T&...>(t); };
                   auto set = [&](auto&... t) noexcept { set_value(std::move(rcvr), std::move(t)...); };
+
+                  on_stop.reset();
                   apply(
                     [&](auto&... opts) noexcept {
                       apply(set, tuple_cat(tie(*opts)...));
@@ -7038,6 +7040,7 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                   disposition::error, evaluates:
 
                   
+                  on_stop.reset();
                   visit(
                     [&]<class Error>(Error& error) noexcept {
                       if constexpr (!same_as<Error, none-such>) {
@@ -7047,7 +7050,12 @@ template<class Domain, class Tag, sender Sndr, class... Args>
                     errors);
                   
- 3. Otherwise, evaluates `set_stopped(std::move(rcvr))`. + 3. Otherwise, evaluates: + +
+                on_stop.reset();
+                set_stopped(std::move(rcvr));
+                
4. The member impls-for<when_all_t>::start is initialized with a callable object equivalent to the following lambda @@ -7060,6 +7068,7 @@ template<class Domain, class Tag, sender Sndr, class... Args> get_stop_token(get_env(rcvr)), on-stop-request{state.stop_src}); if (state.stop_src.stop_requested()) { + state.on_stop.reset(); set_stopped(std::move(rcvr)); } else { (start(ops), ...); From 947473d2c714cad073bdce5dd16c3b6b3abbdf56 Mon Sep 17 00:00:00 2001 From: Lewis Baker Date: Thu, 22 Feb 2024 11:30:04 +1030 Subject: [PATCH 6/8] Fix duplicate numbering of paragraph describing impls-for::complete. Paragraph number 4 was duplicated. Changed to 5. --- execution.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/execution.bs b/execution.bs index 5939b1c..a3d8b58 100644 --- a/execution.bs +++ b/execution.bs @@ -7076,7 +7076,7 @@ template<class Domain, class Tag, sender Sndr, class... Args> }
- 4. The member impls-for<when_all_t>::complete + 5. The member impls-for<when_all_t>::complete is initialized with a callable object equivalent to the following lambda expression: From 267ca4fb0cf98ba44152aa2c4f6aa9311b02fd26 Mon Sep 17 00:00:00 2001 From: Lewis Baker Date: Thu, 22 Feb 2024 13:43:34 +1030 Subject: [PATCH 7/8] Massaged phrasing of TRY-EMPLACE-ERROR and TRY-EMPLACE-VALUE. The "where for subexpressions" phrasing seemed grammatically weird. --- execution.bs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/execution.bs b/execution.bs index a3d8b58..9a99a50 100644 --- a/execution.bs +++ b/execution.bs @@ -7104,8 +7104,7 @@ template<class Domain, class Tag, sender Sndr, class... Args> }
- where for subexpressions `v` and `e`, TRY-EMPLACE-ERROR(v, - e) is equivalent to: + where TRY-EMPLACE-ERROR(v, e), for subexpressions `v` and `e`, is equivalent to:
           try {
@@ -7116,9 +7115,8 @@ template<class Domain, class Tag, sender Sndr, class... Args>
           
if the expression `decltype(auto(e))(e)` is potentially throwing; otherwise, - `v.template emplace(e)`; and where for subexpressions - `c`, `o`, and pack of subexpressions `as`, TRY-EMPLACE-VALUE(c, - o, as...) is equivalent to: + `v.template emplace(e)`; and where TRY-EMPLACE-VALUE(c, + o, as...), for subexpressions `c`, `o`, and pack of subexpressions `as`, is equivalent to:
           try {

From a9e77cb72dff99e0979718bc098b3490b4f5880e Mon Sep 17 00:00:00 2001
From: Lewis Baker 
Date: Thu, 22 Feb 2024 13:47:29 +1030
Subject: [PATCH 8/8] Rephrase wording for
 when_all_with_variant.transform_sender(sndr, env).

- "Let x be subexpressions, such that X is decltype((x))" replaced with "Given subexpressions x ..." and then just use decltype(x) in-place in the one place it was used instead of defining another term for that.
- Refer to the code-block below as "the body of the `transform_sender` member-function" instead of saying the call expression "is equal to" the the code-block.
---
 execution.bs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/execution.bs b/execution.bs
index 9a99a50..ba8095d 100644
--- a/execution.bs
+++ b/execution.bs
@@ -7139,14 +7139,14 @@ template<class Domain, class Tag, sender Sndr, class... Args>
         make-sender(when_all_with_variant, {}, sndr0, ... sndrn-1));
       
-6. Let `sndr` and `env` be subexpressions such that `Sndr` is `decltype((sndr))`. If - sender-for<Sndr, when_all_with_variant_t> is `false`, +6. Given subexpressions `sndr` and `env`, if + sender-for<decltype((sndr)), when_all_with_variant_t> is `false`, then the expression `when_all_with_variant.transform_sender(sndr, env)` is - ill-formed; otherwise, it is equal to: + ill-formed; otherwise, the body of the `transform_sender` member-function is equivalent to:
-      auto [tag, data, ...child] = sndr;
-      return when_all(into_variant(std::move(child))...);
+        auto [tag, data, ...child] = sndr;
+        return when_all(into_variant(std::move(child))...);
       
This causes the `when_all_with_variant(sndr...)` sender