[concurrency-interest] More Javadoc problems

Peter Levart peter.levart at gmail.com
Fri Dec 19 16:10:47 EST 2014


On 12/19/2014 09:20 PM, cowwoc wrote:
> Hi Peter,
>
> That's not what I meant. I meant that we should "throw e1" not "throw 
> e2" near the end. I say this because I am under the impression that 
> join() only fires after whenComplete() completes. Is that not the case?

join() returns (or throws) when cf1 completes (cf1 has been 
asynchronously executing a Supplier in background thread - see 
supplyAsync). At the same time (but in another thread - the thread that 
just completed 'cf1') a whenComplete() BiConsumer is executed. So you 
have two threads (main thread and background thread) both accessing the 
same instance of exception 'e1' at the same time - the outcome of cf1. 
So you can't add 'e2' to the suppressed exceptions of 'e1' in the 
background thread without observing 'e1' being changed in main thread.

>
> Assuming I'm wrong, then I'd advocate an approach similar to what you 
> said: throw a new exception (say e2) but instead of invoking 
> e1.addSuppressed(e2) I'd do it the other way around: 
> e2.addSuppressed(e1). This way main() would see e1 (unmodified) and 
> anyone listening to the new stage would see e2.addSuppressed(e1).
>
> The only problem (as you mentioned) is that the specification/Javadoc 
> took a very undesirable path (throws e1 and ignores e2). I really hope 
> we can change this.

I think the intention of whenComplete is to provide a means of 
post-cleanup. Like implicit close in try-with-resources statement where 
the exception that gets propagated is the main exception from the body 
block. Since completion results can be consumed right-away, it is 
impossible to attach suppressed exceptions later when post-cleanup 
completes.

Why the 2nd stage completes with the same exception as 1st? I think 
because it is designed to complete with the same (exceptional OR 
nonexceptional) result as the 1st. If would be inconsistent to expect 
the same nonexceptional result but different exceptional.

If you want to change the exceptional OR nonexceptional outcome of 
preceeding stage, then use handle() instead of whenComplete().

Regards, Peter

>
> Gili
>
> On 19/12/2014 2:42 PM, Peter Levart wrote:
>>
>> On 12/19/2014 05:45 PM, cowwoc wrote:
>>> Hi Josh,
>>>
>>> Can you give a concrete example where observers would witness 
>>> side-effects?
>>
>> Try this:
>>
>>
>> public class CFTest {
>>
>>     static void sleep(long millis) {
>>         try {
>>             Thread.sleep(millis);
>>         } catch (InterruptedException e) {
>>         }
>>     }
>>
>>     public static void main(String[] args) throws Exception {
>>
>>         CompletableFuture<Integer> cf1 = 
>> CompletableFuture.supplyAsync(() -> {
>>             sleep(200L);
>>             throw new RuntimeException("1st");
>>         });
>>
>>         cf1.whenComplete((i, e1) -> {
>>             if (e1 != null) {
>>                 sleep(100L);
>>                 RuntimeException e2 = new RuntimeException("2nd");
>>                 e1.addSuppressed(e2); // this is what is desired right?
>>                 throw e2;
>>             }
>>         });
>>
>>         try {
>>             cf1.join();
>>         } catch (CompletionException e) {
>>             System.out.println("\n1st print:\n");
>>             e.printStackTrace(System.out);
>>             sleep(200L);
>>             System.out.println("\n2nd print:\n");
>>             e.printStackTrace(System.out);
>>         }
>>     }
>> }
>>
>>>
>>> Assuming what you say is possible, would you object to throwing a 
>>> clone of the original exception instance with the suppressed 
>>> exceptions added? This way only observers of the 2nd completion 
>>> stage would observe these changes.
>>
>> Exceptions are not generally Cloneable.
>>
>> Regards, Peter
>>
>>
>>> Gili
>>>
>>> On 19/12/2014 10:40 AM, Josh Humphries wrote:
>>>> I do not disagree. Though one thing to note of this approach is 
>>>> that "observers" of the original completion stage (that failed with 
>>>> exception 1) will now witness side effects from a *successor* 
>>>> completion stage via the suppressed exception. It might be a little 
>>>> odd for some consumers to see the state of the Throwable change 
>>>> /after/ it has already been (potentially) published to multiple 
>>>> threads.
>>>>
>>>> I would personally vote that the later completion stage fail 
>>>> exceptionally with exception2. But that's a change in behavior that 
>>>> is likely to be a non-starter due to being incompatible with the 
>>>> current spec (even if only slightly).
>>>>
>>>> The actual authors of the library are on this list and can likely 
>>>> chime in further about why it behaves that way.
>>>>
>>>>
>>>>
>>>> ----
>>>> *Josh Humphries*
>>>> Manager, Shared Systems  |  Platform Engineering
>>>> Atlanta, GA  |  678-400-4867
>>>> *Square* (www.squareup.com <http://www.squareup.com>)
>>>>
>>>> On Fri, Dec 19, 2014 at 9:50 AM, cowwoc <cowwoc at bbs.darktech.org 
>>>> <mailto:cowwoc at bbs.darktech.org>> wrote:
>>>>
>>>>     Hi Josh,
>>>>
>>>>     Thanks for the follow-up.
>>>>
>>>>     I'd like to request two changes:
>>>>
>>>>      1. Add exception2 as a suppressed exception (eating exceptions
>>>>         is like silent failures... it's bad business)
>>>>      2. Have the Javadoc to mention what will happen in this case.
>>>>
>>>>
>>>>     Let me know what you think.
>>>>
>>>>     Thanks,
>>>>     Gili
>>>>
>>>>     On 19/12/2014 9:42 AM, Josh Humphries [via JSR166 Concurrency]
>>>>     wrote:
>>>>>     Looking at the source code -- the ultimate spec ;) -- the
>>>>>     original exception is preferred. So in your example, the
>>>>>     resulting CompletionStage completes exceptionally with
>>>>>     exception1, and exception2 is effectively eaten.
>>>>>
>>>>>     ----
>>>>>     *Josh Humphries*
>>>>>     Manager, Shared Systems  |  Platform Engineering
>>>>>     Atlanta, GA  | 678-400-4867 <tel:678-400-4867>
>>>>>     *Square* (www.squareup.com <http://www.squareup.com>)
>>>>>
>>>>>     On Fri, Dec 19, 2014 at 9:00 AM, cowwoc <[hidden email]
>>>>>     <http:///user/SendEmail.jtp?type=node&node=11671&i=0>> wrote:
>>>>>
>>>>>         Hi guys,
>>>>>
>>>>>         The Javadoc for CompletableFuture.whenComplete() reads:
>>>>>
>>>>>         "If the supplied action itself encounters an exception,
>>>>>         then the returned
>>>>>         stage exceptionally completes with this exception unless
>>>>>         this stage also
>>>>>         completed exceptionally."
>>>>>
>>>>>         Huh?!
>>>>>
>>>>>         So if the original stage completed with exception1 but the
>>>>>         handler threw
>>>>>         exception2, which exception does the returned
>>>>>         CompleteableFuture complete
>>>>>         with? The specification says what *won't* happen if the
>>>>>         stage also completed
>>>>>         exceptionally, but it doesn't say what *will* happen.
>>>>>         Please clarify :)
>>>>>
>>>>>         Thanks,
>>>>>         Gili
>>>>>
>>>>>
>>>>>
>>>>>         --
>>>>>         View this message in context:
>>>>>         http://jsr166-concurrency.10961.n7.nabble.com/More-Javadoc-problems-tp11669.html
>>>>>         Sent from the JSR166 Concurrency mailing list archive at
>>>>>         Nabble.com.
>>>>>         _______________________________________________
>>>>>         Concurrency-interest mailing list
>>>>>         [hidden email]
>>>>>         <http:///user/SendEmail.jtp?type=node&node=11671&i=1>
>>>>>         http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>
>>>>>
>>>>>     _______________________________________________
>>>>>     Concurrency-interest mailing list
>>>>>     [hidden email]
>>>>>     <http:///user/SendEmail.jtp?type=node&node=11671&i=2>
>>>>>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>>
>>>>>
>>>>>     ------------------------------------------------------------------------
>>>>>     If you reply to this email, your message will be added to the
>>>>>     discussion below:
>>>>>     http://jsr166-concurrency.10961.n7.nabble.com/More-Javadoc-problems-tp11669p11671.html
>>>>>
>>>>>     To unsubscribe from More Javadoc problems, click here.
>>>>>     NAML
>>>>>     <http://jsr166-concurrency.10961.n7.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>>>>
>>>>
>>>>
>>>>     ------------------------------------------------------------------------
>>>>     View this message in context: Re: More Javadoc problems
>>>>     <http://jsr166-concurrency.10961.n7.nabble.com/More-Javadoc-problems-tp11669p11672.html>
>>>>
>>>>
>>>>     Sent from the JSR166 Concurrency mailing list archive
>>>>     <http://jsr166-concurrency.10961.n7.nabble.com/> at Nabble.com.
>>>>
>>>>     _______________________________________________
>>>>     Concurrency-interest mailing list
>>>>     Concurrency-interest at cs.oswego.edu
>>>>     <mailto:Concurrency-interest at cs.oswego.edu>
>>>>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20141219/8752a3df/attachment-0001.html>


More information about the Concurrency-interest mailing list