<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Holo The Sage Wolf" <holo3146@gmail.com><br><b>To: </b>"Remi Forax" <forax@univ-mlv.fr><br><b>Cc: </b>"Alan Bateman" <Alan.Bateman@oracle.com>, "attila kelemen85" <attila.kelemen85@gmail.com>, "loom-dev" <loom-dev@openjdk.org><br><b>Sent: </b>Sunday, May 14, 2023 5:11:35 PM<br><b>Subject: </b>Re: STS allows to bypass any checked exceptions<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="auto">I think that generally the fact that the interfaces of j.u.function are built without proper exception parameter pushes the problem, and that a more complete solution is to maybe create j.u.f.exceptionally that contains the "correct" implementations.</div></blockquote><div><br></div><div>There is no proper union types in the Java type system so no way to union several exceptions as one type parameter so even if j.u.f interfaces where parametrized by an exception type, the stream API could not have using them properly.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>This is different for STS, for STS you declare the common type of result values upfront when creating the STS so you can also declare the common type of the exceptions too.</div><div>In the detail you also need to single out InterruptedException because otherwise the common supertype should be always Exception.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>That's why the equivalent of a Callable for STS should be<br data-mce-bogus="1"></div><div> interface Invokable<T, E extends Exception> {<br data-mce-bogus="1"></div><div> T invoke() throws E, InterruptedException;<br data-mce-bogus="1"></div><div> }<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>In that case, inside TaskHandle, the method get() becomes<br data-mce-bogus="1"></div><div> interface TaskHandle<T, E extends Exception> {<br data-mce-bogus="1"></div><div> enum State { SUCCESS, FAILED, CANCELLED, RUNNING }<br data-mce-bogus="1"></div><div> State state();<br data-mce-bogus="1"></div><div> T get() throws E, CancelledException<br data-mce-bogus="1"></div><div> }<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>With the CancelledException being thrown either because someone has called STS.shutdown() or because the Invokable throws InterruptedException (via a call to a library by example).</div><div>CancelledException should a runtime exception because the user of STS know if shutdown() can be called (explicitly or implicitly by using the subclasses ShutdownOnXX).<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>This works great especially if STS.handleComplete() does not a TaskHandle as parameter but another object because handleComplete() is not called with a running task or a cancelled task, so that object only need to represent the union SUCCESS(T value) | FAILED(E exception).</div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="auto"><div dir="auto"></div></div></blockquote><div>regards,</div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, May 14, 2023, 17:43 Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">----- Original Message -----<br>
> From: "Alan Bateman" <<a href="mailto:Alan.Bateman@oracle.com" target="_blank" rel="noreferrer">Alan.Bateman@oracle.com</a>><br>
> To: "attila kelemen85" <<a href="mailto:attila.kelemen85@gmail.com" target="_blank" rel="noreferrer">attila.kelemen85@gmail.com</a>><br>
> Cc: "loom-dev" <<a href="mailto:loom-dev@openjdk.org" target="_blank" rel="noreferrer">loom-dev@openjdk.org</a>><br>
> Sent: Sunday, May 14, 2023 3:14:30 PM<br>
> Subject: Re: STS allows to bypass any checked exceptions<br>
<br>
> On 14/05/2023 11:47, Attila Kelemen wrote:<br>
>> :<br>
>> That is - assuming join is invoked without interruption - my problem<br>
>> with the shown behaviour is that the exception thrown by the<br>
>> `Callable` is discarded and an ISE is thrown instead, so we are losing<br>
>> the original exception which could be used for tracking the issue.<br>
> <br>
> The `get` method is used to get the result of as task that completed<br>
> successfully, it's not discarding anything. But maybe you are arguing to<br>
> stay with Future so that Future::get throws ExecutionException with the<br>
> exception as the cause?<br>
<br>
As Attila said, the API of TaskHandle makes it too easy to discard the exception, and and if the exception rarely happens it will be unnecessary hard to debug.<br>
<br>
I think that TaskHandle.get() throwing ISE if STS.join() is not called before is fine because it's a reproducible scenario, throwing ISE if an exception appears in the callable is not fine because it depends on an external factor.<br>
<br>
I think the typ of the exception should be tracked by the type system, what I've called "exception transparency" in a previous mail,<br>
mainly it means that get() should return the value or throw the exception, the type of the exception, like the type of the value should be a type variable.<br>
<br>
By seeing TaskHandle as a Supplier, we are pushing users to ignore exceptions thrown by the callable.<br>
I would prefer taskHandle::get to be convertible to a Supplier only if the callable does not throw an Exception, otherwise taskHandle::get should be convertible to a Callable.<br>
<br>
> <br>
> -Alan.<br>
<br>
Rémi<br>
</blockquote></div><br></blockquote></div></div></body></html>