One-way execute leaves asynchronous failure unspecified
P1525R0 argues that generic execution needs explicit completion channels, including cancellation that cannot be inferred from callback destruction.
An executor can accept a callback and then fail before invoking it. A function that only accepts the callback and returns void needs another way to tell the computation what happened. P1525R0, dated June 17, argues that the proposed one-way execute operation does not define enough of that conversation for generic asynchronous code.
Eric Niebler, Kirk Shoop, Lewis Baker and Lee Howes frame the issue around errors and cancellation. Their argument concerns the operations on which other algorithms must be built. If a required operation omits a completion path, an algorithm layered above it cannot reliably reconstruct that path.
I see a close connection to resource ownership here. C++ destructors provide dependable cleanup when an object's lifetime ends, but the reason an asynchronous computation stopped is a different fact. A design that makes cleanup carry both meanings risks giving generic code too little information.
Submission and execution can fail at different times
The paper defines one-way execute as accepting a nullary callable, returning void and eagerly submitting work. It examines the OneWayExecutor concept in the contemporary executors proposal. Error handling can vary among executor implementations.
An exception during submission can still reach the submitting thread. A failure after submission has returned cannot use that same route. An executor might defer creating its execution agent until later or remove queued work when a deadline expires. Generic code needs a specified channel for that later event.
This distinction affects composition. An algorithm that retries work on another execution context must observe failure on the original context. A logging adapter similarly needs the error before forwarding it. If the executor has already chosen an implementation-specific response, the adapter has no portable point at which to intervene.
The criticism is therefore about information available through the concept. An individual executor can provide sensible local behavior. That does not establish a shared contract under which arbitrary executors can participate in the same higher-level algorithm.
A receiver makes completion explicit
Lewis Baker's earlier P1341R0 explores unifying asynchronous interfaces through sender and receiver abstractions. It attempts to connect executors with coroutines and other asynchronous operations. The paper explicitly describes its direction as exploratory.
In the June paper's terminology, a sender represents a computation and a receiver generalizes a callback. A receiver has a success operation for produced values, an error operation for failure, and a done operation for cancellation. Those names belong to the proposal being discussed, not an installed standard-library interface.
A scheduler produces a sender whose successful completion occurs in the scheduler's execution context. The paper allows the error path to use an unspecified context when the requested context cannot be obtained. That separation is useful because inability to reach the desired execution context must not also prevent reporting the failure.
A fallback scheduler can use that error path to submit the work elsewhere. The normal result path still obeys the original context guarantee when scheduling succeeds. The two paths have different responsibilities, and specifying them separately permits a policy that a single unconditional callback cannot express.
This is a concrete composability requirement. The adapter needs a completion protocol that survives the failure it is meant to handle. An implementation-specific exception handler hidden inside the executor cannot substitute for a receiver chosen by the composing algorithm.
Cancellation is distinct from an execution error
P1525R0 treats cancellation as a normal outcome for useful asynchronous algorithms. Its example is an operation waiting for any of several tasks. Once one task completes, the algorithm can cancel work that is no longer needed. That cancellation need not indicate that a resource allocation or execution agent failed.
Giving cancellation its own channel lets dependent work stop without following the error-handling path. It also lets the caller distinguish a computation that produced no value by policy from one that failed unexpectedly. Those distinctions affect what a composed operation should report.
The proposal's vocabulary is still evolving. The important claim is the separation of meanings. A completion protocol must explain the absence of a successful result without forcing every such absence into the same category.
I favor explicit cancellation semantics because the application often knows why work has become unnecessary. Preserving that fact through composition gives the caller a better basis for policy than an undifferentiated indication that no callback ran.
Destruction cannot identify cancellation by itself
A callback object can be destroyed after success or failure. A moved-from callback can also be destroyed, and a canceled callback can reach destruction without invocation. The lifetime event alone does not identify which of these occurred.
The paper argues that inferring cancellation through a destructor therefore requires additional state. The object must distinguish its cancellation case from ordinary cleanup. Exception unwinding creates another question about whether the destruction represents an error or a cancellation.
An executor that removes queued work already has information about whether that work has executed. The authors argue it can communicate cancellation before destroying the work item. This places the semantic notification at the operation that knows why execution will not happen.
RAII remains responsible for cleanup. An explicit completion notification supplies a reason that cleanup does not intrinsically carry. Keeping those roles separate makes it easier to compose an asynchronous result with a resource's ordinary lifetime.
Ownership also affects allocation
The June paper describes scheduling a coroutine using queue state stored in its frame. A schedule operation returning an awaitable sender can let the awaiter provide that storage. This can avoid an additional allocation for a continuation.
It also sketches splitting submission into a connection operation that creates state and a start operation that initiates work. In that model, the caller must keep the state alive until completion. That is a lifetime obligation attached to the proposed efficiency benefit.
Baker's earlier paper explains why ownership direction matters when adapting callbacks and coroutines. A producer that cannot assume the callback survives submission generally needs to retain it. A suspended coroutine can instead retain operation state inside its own lifetime.
P1525R0 is an argument about the foundation on which generic algorithms can depend. Explicit error and cancellation paths let adapters preserve information across scheduling failure. The ownership discussion adds a separate requirement, that the interface reveal enough about operation state for callers to place and retain it efficiently.