RFR: jsr166 jdk9 integration wave 2

Doug Lea dl at cs.oswego.edu
Wed Dec 16 14:09:28 UTC 2015


On 12/02/2015 07:51 PM, Martin Buchholz wrote:
> We're stuck.  Peter wants to make Throwables cloneable, I want to
> reverse the order of throwables and add the past Throwable as a
> suppressed exception to the exception of a dependent action, and Doug
> wants the current webrev behavior of adding the dependent action as a
> suppressed exception of the source.
>

After letting this sit for a week or so, I think the main issue
here is that we do not properly explain how and when to use
whenComplete() vs handle(). We should explain that handle()
should be used in the same way as "catch", and whenComplete as
"finally"/try-with-resources. See below.

Given this, the most appropriate response in whenComplete upon
a secondary exception encountered when handling the primary exception
is the same as the finally-based scheme used in try-with-resources:
primary.addSuppressed(secondary).  Which we should have done
originally (vs dropping secondary), and is the current proposed
webrev.

(In contrast, if someone would like to translate one exception
into another by throwing the new one, they could use handle().)

Peter raised the issue that addSuppressed could visibly (but safely)
alter the primary while it is visible to some concurrent action.
Which is true, but also no different than is possible with
try-with-resources (consider that the primary exception there could
be already somehow accessible). If exceptions were cloneable,
it might be less surprising to users in both cases to create a new
cloned exception with the suppressed secondary. But I think we now
agree that pseudo-cloning exceptions has even more opportunity for
surprising users, so should be done only when there aren't any
alternatives.

Agreed?

Here's a clarification for CompletionStage (un-reformatted).
Improvements welcome. Someday we might consider adding some examples.

    *
    * <li>Two method forms support processing whether the triggering
    * stage completed normally or exceptionally: Method {@link
!  * #whenComplete whenComplete} allows injection of an action
    * regardless of outcome, otherwise preserving the outcome in its
!  * completion. Method {@link #handle handle} additionally allows the
    * stage to compute a replacement result that may enable further
    * processing by other dependent stages.  In all other cases, if a
    * stage's computation terminates abruptly with an (unchecked)
--- 58,66 ----
    *
    * <li>Two method forms support processing whether the triggering
    * stage completed normally or exceptionally: Method {@link
!  * #whenComplete whenComplete} is similar to a {@code finally} clause, 
allowing injection of an action
    * regardless of outcome, otherwise preserving the outcome in its
!  * completion. Method {@link #handle handle} is similar to a {@code catch} 
clause, allowing the
    * stage to compute a replacement result that may enable further
    * processing by other dependent stages.  In all other cases, if a
    * stage's computation terminates abruptly with an (unchecked)




More information about the core-libs-dev mailing list