RFR: jsr166 jdk9 integration wave 2

Doug Lea dl at cs.oswego.edu
Mon Nov 23 14:12:50 UTC 2015

On 11/23/2015 04:54 AM, Peter Levart wrote:

> In CompletableFuture.uniWhenComplete method, the possible exception thrown from
> BiConsumer action is added as suppressed exception to the exception of the
> previous stage. This updated exception is then passed as completion result to
> next stage. When previous stage is appended with more than one asynchronous
> continuation:
> ...then both secondary exceptions are added as suppressed to the same primary
> exception:
> This is not nice for two reasons:
> - Throwable::addSuppressed is not thread-safe
> - The consumer of the result of one CompletableFuture can see the exceptional
> result being modified as it observes it.

Thanks. The minimal solution is to lock, at least avoiding conflict
among multiple whenCompletes:

!                 else if (x != ex)
!                     x.addSuppressed(ex);

--- 771,781 ----

!                 else if (x != ex) {
!                     synchronized (x) {
!                         x.addSuppressed(ex);
!                     }
!                 }

This is not as good a solution as your proposal to add Throwable.clone(),
but we should do this until something like clone is in place.

> When this stage is complete, the given action is invoked with the result (or
> null if none) and the exception (or null if none) of this stage as arguments.
> The returned stage is completed when the action returns. If the supplied action
> itself encounters an exception, then the returned stage exceptionally completes
> with this exception unless this stage also completed exceptionally."
> Could specification be tweaked a bit? The last statement leaves it open to what
> actually happens when "this stage also completes exceptionally".

The looseness was intentional. We'd like to improve debuggability of
implementations without strictly promising a particular form in interfaces.
This is similar to what's done in ForkJoinTask, where we try to
relay exception causes from other threads, but can't promise anything
beyond a plain exception.


More information about the core-libs-dev mailing list