You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: source/network-endeavor/todo/d4007-senders-and-coros.md
+26-9Lines changed: 26 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
---
2
2
title: "Info: Open Issues in `std::execution::task`"
3
-
document: D4007R1
4
-
date: 2026-03-12
3
+
document: P4007R2
4
+
date: 2026-04-08
5
5
reply-to:
6
6
- "Vinnie Falco <vinnie.falco@gmail.com>"
7
7
- "Mungo Gill <mungo.gill@me.com>"
@@ -10,12 +10,19 @@ audience: LEWG
10
10
11
11
## Abstract
12
12
13
-
`std::execution::task` ([P3552R3](https://wg21.link/p3552r3)<sup>[1]</sup>) has open issues identified by national ballot comments, LWG issues, and published papers. This paper classifies each issue by whether it can be resolved after C++26 ships or whether shipping forecloses the fix.
13
+
`std::execution::task` ([P3552R3](https://wg21.link/p3552r3)<sup>[1]</sup>) had open issues identified by national ballot comments, LWG issues, and published papers. Croydon resolved several. This paper classifies each issue by whether it can be resolved after C++26 ships or whether shipping forecloses the fix, and notes which classified issues were addressed at Croydon.
14
14
15
15
---
16
16
17
17
## Revision History
18
18
19
+
### R2: April 2026 (post-Croydon)
20
+
21
+
* Updated classification to reflect Croydon motions 28-29, 33, 35-38.
22
+
Acknowledged issues resolved by P3941R4, P3927R2, P3980R1, and P4151R1.
23
+
Rewrote allocator descriptions to credit P3980R1 while preserving
24
+
residual frame-allocator concerns.
25
+
19
26
### R1: March 2026 (prior to Croydon meeting)
20
27
21
28
* Complete rewrite as an informational classification of open issues.
@@ -42,7 +49,11 @@ This paper asks for nothing.
42
49
43
50
`task`'s `promise_type` is a class template instantiated in user code. Its `operator new`, allocator selection, stop token storage, environment forwarding, and destruction ordering can change between standard revisions without binary incompatibility. These issues are fixable post-ship: [Unusual Allocator Customisation](https://wg21.link/p3796r1)<sup>[3]</sup>, [Flexible Allocator Position](https://wg21.link/p3796r1)<sup>[3]</sup>, [Shadowing The Environment Allocator](https://wg21.link/p3796r1)<sup>[3]</sup>, [Stop Source Always Created](https://wg21.link/p3796r1)<sup>[3]</sup>, [Stop Token Default Constructible](https://wg21.link/p3796r1)<sup>[3]</sup>, [Task Not Actually Lazily Started](https://wg21.link/p3796r1)<sup>[3]</sup>, [Frame Destroyed Too Late](https://wg21.link/p3796r1)<sup>[3]</sup>, [No Default Arguments](https://wg21.link/p3796r1)<sup>[3]</sup>, [`unhandled_stopped` Not `noexcept`](https://wg21.link/p3796r1)<sup>[3]</sup>, [Environment Design Inefficient](https://wg21.link/p3796r1)<sup>[3]</sup>, [Non-Sender Awaitables Unsupported](https://wg21.link/p3796r1)<sup>[3]</sup>, [Future Language Feature Could Avoid `co_yield`](https://wg21.link/p3796r1)<sup>[3]</sup>, [No TLS Capture/Restore Hook](https://wg21.link/p3796r1)<sup>[3]</sup>, [`return_value`/`return_void` Have No Specification](https://wg21.link/p3796r1)<sup>[3]</sup>, [`co_return { args... }` Unsupported](https://wg21.link/p3796r1)<sup>[3]</sup>, [`change_coroutine_scheduler` Requires Assignable Scheduler](https://wg21.link/p3796r1)<sup>[3]</sup>, [Sender-Unaware Coroutines Cannot `co_await` a `task`](https://wg21.link/p3796r1)<sup>[3]</sup>, [Missing Rvalue Qualification](https://wg21.link/p3796r1)<sup>[3]</sup>, [Parameter Lifetime Is Surprising](https://wg21.link/p3801r0)<sup>[4]</sup>, [No Protection Against Dangling References](https://wg21.link/p3801r0)<sup>[4]</sup>, [`co_yield with_error` Is Clunky](https://wg21.link/p3801r0)<sup>[4]</sup>, [`co_await schedule(sch)` Is an Expensive No-Op](https://wg21.link/p3801r0)<sup>[4]</sup>, [Coroutine Cancellation Is Ad-Hoc](https://wg21.link/p3801r0)<sup>[4]</sup>.
44
51
45
-
`affine_on` semantics, rescheduling behavior, and algorithm customisation are specification-level concerns. Tightening requirements or adding default implementations does not change any published interface. These issues are fixable post-ship: [`affine_on` Default Implementation Lacks Specification](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Semantics Not Clear](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Shape May Not Be Correct](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Shouldn't Forward Stop Requests](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Customisation For Other Senders](https://wg21.link/p3796r1)<sup>[3]</sup>, [Starting a `task` Reschedules Unconditionally](https://wg21.link/p3796r1)<sup>[3]</sup>, [Resuming After a `task` Reschedules Unnecessarily](https://wg21.link/p3796r1)<sup>[3]</sup>, [`bulk` vs. `task_scheduler`](https://wg21.link/p3796r1)<sup>[3]</sup>, [No Completion Scheduler](https://wg21.link/p3796r1)<sup>[3]</sup>, [`with_awaitable_senders` Unused](https://wg21.link/p3796r1)<sup>[3]</sup>.
52
+
Of these, Croydon resolved six: Unusual Allocator Customisation, Flexible Allocator Position, and Shadowing The Environment Allocator were addressed by [P3980R1](https://wg21.link/p3980r1)<sup>[5]</sup>; `unhandled_stopped` Not `noexcept`, `change_coroutine_scheduler` Requires Assignable Scheduler (the mechanism was removed entirely), and Missing Rvalue Qualification were addressed by [P3941R4](https://wg21.link/p3941r4)<sup>[15]</sup>. The remaining issues are still open and fixable post-ship.
53
+
54
+
`affine` semantics (formerly `affine_on`, renamed by [P4151R1](https://wg21.link/p4151r1)<sup>[16]</sup>), rescheduling behavior, and algorithm customization are specification-level concerns. Tightening requirements or adding default implementations does not change any published interface. These issues are fixable post-ship: [`affine_on` Default Implementation Lacks Specification](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Semantics Not Clear](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Shape May Not Be Correct](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Shouldn't Forward Stop Requests](https://wg21.link/p3796r1)<sup>[3]</sup>, [`affine_on` Customisation For Other Senders](https://wg21.link/p3796r1)<sup>[3]</sup>, [Starting a `task` Reschedules Unconditionally](https://wg21.link/p3796r1)<sup>[3]</sup>, [Resuming After a `task` Reschedules Unnecessarily](https://wg21.link/p3796r1)<sup>[3]</sup>, [`bulk` vs. `task_scheduler`](https://wg21.link/p3796r1)<sup>[3]</sup>, [No Completion Scheduler](https://wg21.link/p3796r1)<sup>[3]</sup>, [`with_awaitable_senders` Unused](https://wg21.link/p3796r1)<sup>[3]</sup>.
55
+
56
+
Of these, Croydon resolved eight. [P3941R4](https://wg21.link/p3941r4)<sup>[15]</sup> rewrote scheduler affinity from scratch - `affine_on` was made unary, `change_coroutine_scheduler` removed, and `get_start_scheduler` introduced - resolving the five `affine_on`/`affine` items and both rescheduling items. [P4151R1](https://wg21.link/p4151r1)<sup>[16]</sup> renamed `affine_on` to `affine`. [P3927R2](https://wg21.link/p3927r2)<sup>[17]</sup> resolved `bulk` vs. `task_scheduler` by giving `task_scheduler` parallel bulk support. Two items remain open: No Completion Scheduler and `with_awaitable_senders` Unused.
46
57
47
58
---
48
59
@@ -52,14 +63,14 @@ The issues in this section are items where shipping forecloses the fix.
| Error Return |[P3950R0](https://wg21.link/p3950r0)<sup>[8]</sup>, [P3801R0](https://wg21.link/p3801r0)<sup>[4]</sup>, [P1713R0](https://wg21.link/p1713r0)<sup>[9]</sup> | no |
58
69
| Symmetric Transfer |[P2583R3](https://isocpp.org/files/papers/P2583R3.pdf)<sup>[10]</sup>, [US 246-373](https://github.com/cplusplus/nbballot/issues/948)<sup>[11]</sup>, [LWG 4348](https://cplusplus.github.io/LWG/issue4348)<sup>[12]</sup>, [P3801R0](https://wg21.link/p3801r0)<sup>[4]</sup>, [P3796R1](https://wg21.link/p3796r1)<sup>[3]</sup> | no |
59
70
60
-
-**Allocator Timing.**`task` does not allow the user to specify an allocator at the launch site for coroutine frame allocation. The coroutine frame is allocated by `operator new`at the call site, before any sender `connect`/`start`machinery runs. The receiver's environment - which carries the allocator - is not yet available at that point. The `allocator_arg` mechanism in [P3552R3](https://wg21.link/p3552r3)<sup>[1]</sup> works around this by requiring the allocator in the coroutine's parameter list, but that locks in a caller-specified approach and forecloses environment-based injection.
71
+
-**Allocator Timing.**[P3980R1](https://wg21.link/p3980r1)<sup>[5]</sup> separates frame allocation from environment allocation: the environment allocator is now sourced from `get_allocator(get_env(rcvr))`at `connect` time, resolving environment-based injection. The frame allocator, however, remains call-site-specified via `allocator_arg` in the coroutine parameter list. This is a structural consequence of coroutine allocation timing - the frame is allocated by `operator new` before `connect`/`start` runs, so the receiver's environment is unavailable. Shipping standardizes the two-tier split. A design where frame allocation participates in environment-based propagation is foreclosed without a language change to coroutine allocation.
61
72
62
-
-**Allocator Propagation.**`task`does not propagate the frame allocator to child tasks. Each child task allocates its frame independently. Shipping without propagation locks in a design where every launch site must specify its allocator explicitly, foreclosing transparent propagation through the coroutine call tree.
73
+
-**Allocator Propagation.**[P3980R1](https://wg21.link/p3980r1)<sup>[5]</sup> provides environment allocator propagation: each `task`obtains its environment allocator from `get_allocator(get_env(rcvr))`, so a parent's environment allocator flows to children through the receiver chain. Frame allocator propagation remains absent. Each coroutine call site must independently specify `allocator_arg` to use a non-default frame allocator. In a deep coroutine call tree where frame allocation matters - arena-per-request, pool allocators, device memory - every function signature must carry `allocator_arg`explicitly. Shipping this design forecloses automatic frame allocator propagation through the coroutine call tree.
63
74
64
75
-**Error Return.**`task` requires `co_yield with_error(e)` to propagate an error to the caller. `co_return` cannot carry an error value because `return_value` and `return_void` are mutually exclusive in the current coroutine specification. Shipping this interface locks in the `co_yield` mechanism and forecloses `co_return`-based error propagation, which would require a language change.
65
76
@@ -83,7 +94,7 @@ Papers, issues, and ballot comments referenced in this document.
6.[LWG 4356](https://cplusplus.github.io/LWG/issue4356) - "connect() should use get_allocator(get_env(rcvr))". https://cplusplus.github.io/LWG/issue4356
88
99
7.[US 254-385](https://github.com/cplusplus/nbballot/issues/960) - C++26 NB ballot comment. https://github.com/cplusplus/nbballot/issues/960
89
100
8.[P3950R0](https://wg21.link/p3950r0) - "return_value & return_void Are Not Mutually Exclusive" (Robert Leahy, 2025). https://wg21.link/p3950r0
@@ -97,3 +108,9 @@ Papers, issues, and ballot comments referenced in this document.
97
108
98
109
14.[C++ Working Draft](https://eel.is/c++draft/) - (Richard Smith, ed.). https://eel.is/c++draft/
0 commit comments