cplusplus / sender-receiver

Issues list for P2300
Apache License 2.0
18 stars 3 forks source link

`bulk` does not specify what customizations need to do with exceptions thrown from invocations of `f` #276

Open lewissbaker opened 1 month ago

lewissbaker commented 1 month ago

The current wording of bulk() in P2300R10 has a default implementation that invokes set_error(rcvr, current_exception()) if any of the invocations of f exit with an exception.

However, this strategy only works for sequential execution implementation strategies.

We need to specify what the semantics should be if f exits with an exception during implementations of bulk that execute f concurrently.

Several options come to mind:

  1. do not execute f concurrently if f is potentially throwing
  2. require that f is noexcept
  3. pick an arbitrary exception thrown by one of the invocations of f
  4. pick the first exception thrown by an invocation of f - e.g. decided by some atomic-rmw operation.
  5. reduce the exceptions into a single error value (perhaps by some user-provided reduction operation)
  6. terminate on error (this would be inconsistent with the well-defined behaviour of the default sequential implementation)
  7. encapsulate thrown exceptions into an exception_list but only guarantee that one exception exists in it - implementations may gather multiple of the exceptions

Also, what should the behaviour be for subsequent invocations of f? Should we try to cancel subsequent invocations of f after an invocation of f has exited with an exception? Or should it still try to call all subsequent invocations of f (this might be a reasonable strategy if we are reducing the errors)?

What if a stop-request is issued after the f operation exits with an exception but before the executions on other threads can stop executing? Should the operation as a whole complete with set_error or should it complete with set_stopped?

dietmarkuehl commented 1 month ago

I recall that the issue of how to deal with exceptions in concurrent algorithms was discussed at the Oulu meeting: there was a heated debate which couldn’t be settled. It may be worth to look at that discussion. For example http://wg21.link/p0323 (exception_list) and http://wg21.link/p0333 (improving parallel algorithm exception handling) are in that space. The current parallel algorithms may also have an approach.On 12 Jul 2024, at 07:13, Lewis Baker @.***> wrote: The current wording of bulk() in P2300R10 has a default implementation that invokes set_error(rcvr, current_exception()) if any of the invocations of f exit with an exception. However, this strategy only works for sequential execution implementation strategies. We need to specify what the semantics should be if f exits with an exception during implementations of bulk that execute f concurrently. Several options come to mind:

do not execute f concurrently if f is potentially throwing pick an arbitrary exception thrown by one of the invocations of f pick the first exception thrown by an invocation of f - e.g. decided by some atomic-rmw operation. reduce the exceptions into a single error value (perhaps by some user-provided reduction operation) terminate on error (this would be inconsistent with the well-defined behaviour of the default sequential implementation)

Also, what should the behaviour be for subsequent invocations of f? Should we try to cancel subsequent invocations of f after an invocation of f has exited with an exception? Or should it still try to call all subsequent invocations of f (this might be a reasonable strategy if we are reducing the errors)? What if a stop-request is issued after the f operation exits with an exception but before the executions on other threads can stop executing? Should the operation as a whole complete with set_error or should it complete with set_stopped?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: @.***>

lewissbaker commented 4 weeks ago

The current parallel algorithms are specified to terminate if any of the element-access functions or the per-element operation to be performed exits with an exception - there is no attempt to try to combine the errors together.

That would be one way to approach this - terminate if anything fails within a bulk() operation. However, that would be inconsistent with the current specification of the default bulk implementation, which completes with an exception_ptr of the first exception to be thrown.