STS allows to bypass any checked exceptions

Holo The Sage Wolf holo3146 at gmail.com
Sun May 14 17:10:14 UTC 2023


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.

This is correct (although union type alone is not enough for the Stream
API, see [1]), but this is not an excuse to not add a better standards for
other places (e.g. the ScopedValues)

need to single out InterruptedException

It honestly escaped my mind, greate point.

If we are already on the subject, as you stated, STS#handleComplete has
only 2 possible states, success and failure, so why not completely separate
them:

STS#handleSuccess(T result, Callable task [, boolean cancelled])
STS#handleFailure(Throwable exception, Callable task [, boolean cancelled])
(note that we can’t use parameterize exception here)

[1] https://mail.openjdk.org/pipermail/amber-dev/2023-March/007858.html

On Sun, May 14, 2023 at 7:30 PM <forax at univ-mlv.fr> wrote:

>
>
> ------------------------------
>
> *From: *"Holo The Sage Wolf" <holo3146 at gmail.com>
> *To: *"Remi Forax" <forax at univ-mlv.fr>
> *Cc: *"Alan Bateman" <Alan.Bateman at oracle.com>, "attila kelemen85" <
> attila.kelemen85 at gmail.com>, "loom-dev" <loom-dev at openjdk.org>
> *Sent: *Sunday, May 14, 2023 5:11:35 PM
> *Subject: *Re: STS allows to bypass any checked exceptions
>
> 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.
>
>
> 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.
>
> 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.
> In the detail you also need to single out InterruptedException because
> otherwise the common supertype should be always Exception.
>
> That's why the equivalent of a Callable for STS should be
>   interface Invokable<T, E extends Exception> {
>    T invoke() throws E, InterruptedException;
>  }
>
> In that case, inside TaskHandle, the method get() becomes
>   interface TaskHandle<T, E extends Exception> {
>    enum State { SUCCESS, FAILED, CANCELLED, RUNNING }
>    State state();
>    T get() throws E, CancelledException
>  }
>
> 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).
> CancelledException should a runtime exception because the user of STS know
> if shutdown() can be called (explicitly or implicitly by using the
> subclasses ShutdownOnXX).
>
> 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).
>
> regards,
> Rémi
>
>
> On Sun, May 14, 2023, 17:43 Remi Forax <forax at univ-mlv.fr> wrote:
>
>> ----- Original Message -----
>> > From: "Alan Bateman" <Alan.Bateman at oracle.com>
>> > To: "attila kelemen85" <attila.kelemen85 at gmail.com>
>> > Cc: "loom-dev" <loom-dev at openjdk.org>
>> > Sent: Sunday, May 14, 2023 3:14:30 PM
>> > Subject: Re: STS allows to bypass any checked exceptions
>>
>> > On 14/05/2023 11:47, Attila Kelemen wrote:
>> >> :
>> >> That is - assuming join is invoked without interruption - my problem
>> >> with the shown behaviour is that the exception thrown by the
>> >> `Callable` is discarded and an ISE is thrown instead, so we are losing
>> >> the original exception which could be used for tracking the issue.
>> >
>> > The `get` method is used to get the result of as task that completed
>> > successfully, it's not discarding anything. But maybe you are arguing to
>> > stay with Future so that Future::get throws ExecutionException with the
>> > exception as the cause?
>>
>> 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.
>>
>> 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.
>>
>> I think the typ of the exception should be tracked by the type system,
>> what I've called "exception transparency" in a previous mail,
>> 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.
>>
>> By seeing TaskHandle as a Supplier, we are pushing users to ignore
>> exceptions thrown by the callable.
>> 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.
>>
>> >
>> > -Alan.
>>
>> Rémi
>>
>
>

-- 
Holo The Wise Wolf Of Yoitsu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230514/283d49e2/attachment-0001.htm>


More information about the loom-dev mailing list