[concurrency-interest] CompletableFuture.whenComplete survey

Joe Bowbeer joe.bowbeer at gmail.com
Mon Dec 21 14:28:57 EST 2015


Thanks for clarifying!

I had to read the spec several more times before I could parse that
meaning, but now that I see it, it is also hard to mistake :-)

The spec talks about "this stage" and the "returned stage" and I was
confused by all the "this".

In the spec wording, below, "this stage" is stage1 throwing exception1 and
the "returned stage" is stage2 throwing exception2. The last phrase
contains a "this exception" referring to exception2 and also a "this stage"
referring to stage1, which is especially confusing.

Annotated:

"If the supplied action [action2] itself encounters an exception
[exception2], then the returned stage [stage2] exceptionally completes with
this exception [exception2] unless this stage [stage1] also completed
exceptionally [exception1]."

I had been interpreting the final "this stage" to mean the next stage...

Given my new understanding of the spec, throwing exception1 with suppressed
exception2 (a la try-with-resources) makes a lot of sense.

To be clear, is the current jdk8 behavior *not* compliant with spec?


On Mon, Dec 21, 2015 at 10:49 AM, Doug Lea <dl at cs.oswego.edu> wrote:

> On 12/21/2015 01:12 PM, joe.bowbeer at gmail.com wrote:
>
>> In the second survey email, the only options clearly *compatible* with the
>> CompletionStage spec are ...
>>
>
> No. Here's jdk8 spec:
>
> "If the supplied action itself encounters an exception, then the returned
> stage exceptionally completes with this exception unless this stage also
> completed exceptionally."
>
> Which describes options A and B. Option B also adds as suppressed
> the whenComplete exception, which is not required but not disallowed
> by current spec.
>
> Options C would comply only if the "unless" clause were dropped.
>
> Options D and E would require more changes.
>
> where, as a reminder...
>
>   CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
>      if (true)
>         throw new FirstException();
>      else
>         return "A";
>    });
>
>   CompletableFuture<String> f2 = f1.whenComplete((result, exception) -> {
>     if (true)
>        throw new SecondException();
>    });
>
> A. The FirstException. In other words, preserve the source outcome (only)
> if exceptional, ignoring the SecondException.
>
> B. The FirstException, with the SecondException as its suppressed
> exception.  In other words, preserve but modify the source exception to
> record the SecondException.
>
> C. The SecondException. In other words, replace the source outcome
> (whether it is exceptional or not).
>
> D. The SecondException, with the FirstException as its suppressed
> exception.  In other words, replace the source outcome, but if exceptional,
> record it as a suppressedException of the SecondException.
>
> E. A new CompletionException, with the FirstException as its cause and the
> SecondException as its suppressed exception. In other words, indicate that
> throwing an exception in whenComplete is a different form of error.
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20151221/b833a884/attachment.html>


More information about the Concurrency-interest mailing list