RFR: jsr166 jdk9 integration wave 2

Peter Levart peter.levart at gmail.com
Mon Nov 23 15:27:26 UTC 2015


On 11/23/2015 03:12 PM, Doug Lea wrote:
> 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.

Sorry for confusion. I now noticed that Throwable.addSuppressed() and 
getSuppressed() methods are actually synchronized! I don't know how I 
missed that...

So above patch is not needed. Even printing uses getSuppressed() that 
returns a snapshot. So the only thing remaining is the behavior that 
exceptions can change while they are being observed. If this is 
acceptable then this whole report of mine is just a bunch of misinformation.

Regards, Peter

>> 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.
> -Doug

More information about the core-libs-dev mailing list