STS allows to bypass any checked exceptions
Ron Pressler
ron.pressler at oracle.com
Wed May 17 12:13:44 UTC 2023
What you say is true and by design.
The correct use of STS requires the centralised handling of exceptions by the policy before calling get, or careful use by those opting not to use a policy. In your example, the API is clearly used incorrectly regardless of what TemperatureSensor.temperature does, as there is no centralised handling of exception before get(). The correct use of the API looks like this:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var temperatureHandle = scope.fork(gearboxTemperatureSensor::temperature);
// ...
scope.join().throwIfFailed();
if (temperatureHandle.get() > GEARBOX_TEMPERATURE_LIMIT) // get is guaranteed to succeed
emergencyStop();
} catch (ExecutionException ex) {
// now you must handle exceptions
}
Forcing the correct use of the API has some downsides (see https://mail.openjdk.org/pipermail/loom-dev/2023-May/005601.html) so we’ve so far opted to allow for the possibility of incorrect use and have the JEP and Javadoc inform developers how to use the API correctly.
If people frequently end up accidentally using the API incorrectly, we may well change our stance on this.
— Ron
> On 17 May 2023, at 05:25, Alec Petridis <alec at xz.ax> wrote:
>
> The asymmetry between exception declaration & handling in TaskHandle#get and Callable#call makes it so changes to the throws declaration of a method passed to StructuredTaskScope#fork can be inadvertently ignored until they cause a problem at runtime.
>
>
>
> If you were a downstream consumer of an interface like
>
> interface TemperatureSensor {
>
> double temperature();
>
> }
>
> and TemperatureSensor#temperature()'s fallibility changed, existing non-STS usages of the method would not compile:
>
> interface TemperatureSensor {
>
> double temperature() throws I2CException;
>
> }
>
> gearboxSensor.temperature(); // compile error: checked exception not caught
>
> while existing usages of the method in calls to StructuredTaskScope#fork would compile:
>
>
> try (var scope = new StructuredTaskScope<>()) {
>
> var temperatureHandle = scope.fork(gearboxTemperatureSensor::temperature);
>
> // ...
>
> scope.join();
>
> if (temperatureHandle.get() > GEARBOX_TEMPERATURE_LIMIT) // newly-added checked exception I2CException is not handled
>
> emergencyStop();
>
> }
>
>
>
> A TaskHandle seems a bit like a nullable value in this regard: it's not clear from the declaration point whether a presence check is required before the inner value is accessed.
>
>
>
> Regards,
>
> Alec
>
More information about the loom-dev
mailing list