Changes to JEP 453

Remi Forax forax at univ-mlv.fr
Tue May 23 14:03:32 UTC 2023


----- Original Message -----
> From: "Ron Pressler" <ron.pressler at oracle.com>
> To: "loom-dev" <loom-dev at openjdk.org>
> Sent: Tuesday, May 23, 2023 3:05:11 PM
> Subject: Re: Changes to JEP 453

> Hi.
> 
> The ensuing discussion has led us to another change of heart, as many of the
> cases that were brought up were about uses of StructuredTaskScope in ways for
> which it wasn't intended. Since STS is the first explicit introduction of
> structured concurrency to the JDK, we feel it is important to steer users to
> its intended use. In particular, when tracking the state of individual forks,
> we should report the state *only insofar as the scope should be concerned*.
> 
> The scope treats the forks as a unit and must not concern itself with forks that
> cannot contribute to the scope's own outcome. The scope, preferably through a
> subclass implementing a shutdown policy, should describe how the forks'
> outcomes are composed to produce the scope's outcome but should show no further
> interest in the outcome of the individual forks. The code inside the scope's
> block performs not only the joining and handling of results, but also the
> forking, and so manipulating individual forks through functional composition
> (i.e. by wrapping the forked subtask) is always possible, and is an appropriate
> use of the API. Therefore:
> 
> 1. A call to shutdown indicates that the scope has no interest in further
> results. Consequently, handleComplete will not be called for tasks that have
> not completed before shutdown (including tasks that were forked after
> shutdown); as before, handleComplete will only be called for forks in the
> SUCCESS/FAILED state. Tracking the state of individual forks following a
> shutdown for observability purposes (such as logging) should be done in the
> fork itself (this is always possible through functional composition).

Good idea !

> 
> 2. While we recommend using a shutdown policy, we (still) don't require one.
> When a policy isn't used, the purpose of Subtask.state() is only to indicate
> whether it is legal to call Subtask.get() xor Subtask.exception(), and so
> Subtask.State now has only three values: SUCCESS (get() will return
> successfully), FAILED (exception() will return successfully), and UNAVAILABLE
> (neither method may be called). The UNAVAILABLE state indicates one of the
> following: 1. the subtask was forked but has not yet completed, 2. the subtask
> completed after shutdown, 3. the subtask was forked after shutdown and has
> therefore not started. An UNAVAILABLE state may or may not change to
> SUCCESS/FAILED (in practice, it will not change after join completes
> *normally*).

merging RUNNING and NOT_RUN into UNAVAILABLE is a good idea too.

> 
> As for exceptions, an exception in any fork may either contribute to the scope's
> ultimate failed outcome (as in the case of ShutdownOnFailure and
> ShutdownOnSuccess) or be turned into a value that will be composed into the
> result (as in the runAll example in the JEP). In the latter case, the intent of
> "I want to use the exception of this fork as a value", should be expressed by
> returning that exception from the fork rather than by throwing it; a fork that
> contributes positively to the scope's successful result is, after all, a
> successful fork. Even with some exception transparency mechanism (including as
> a future language feature), the type of an individual fork's exception could
> only matter only in that latter case, and then its type could be expressed
> through the existing single type parameter (fork's U / Subtask's T).

And here i disagree :)

If a STS has no a shutdown policy, I believe there is a missing method "result" in SubTask that works like ShutdownOnSucess.result().
It may either return a result (SUCCESS), throw an ExceptionException (FAILED) or throw UnavailableException (UNAVAILABLE).
Obviously, this method can be written with the current API (state() + get() or exception()) but it will be very convenient to have it, and unify how the different STSs work.

Exception transparency is orthogonal to a specific policy (or no policy), it's a way to avoid exception erasure (exception seen as a Throwable) and its wrapping into ExecutionException.
The wrapping into ExecutionException is quite bad because make the composition of several STSs awkward because the type of the lambda submitted to a fork and the type of exception thrown by the method containing the try-with-resources with a STS are not the same.  

Exception transparency is a way to replace the wrapping ExceptionException by a more precise exception tracked by the type system enabling easier composition.


> 
> The JEP and the Javadoc now reflect these changes.
> 
> We may rename Subtask yet again before this JEP is targeted.
> 
> -- Ron

regards,
Rémi

> 
> 
>> On 18 May 2023, at 19:59, Ron Pressler <ron.pressler at oracle.com> wrote:
>> 
>> Hi.
>> 
>> We have made several changes to structured concurrency (JEP 453) due to
>> feedback:
>> 
>> 1. We've renamed `TaskHandle` to `Subtask`. I can't promise it's the last rename
>> :)
>> 
>> 2. We've fixed the generic signature of handleComplete (thank you Rémi for
>> pointing out the mistake)
>> 
>> 3. We've changed the states and behaviour of subtasks on cancellation. Subtasks
>> that are forked after `shutdown` is called will have the `STILLBORN` state.
>> Running subtasks will be interrupted, but the state of their `Subtask` will
>> remain `RUNNING` until completed, probably sometime after `join` has returned,
>> because `join` returns immediately when `shutdown` is called. When completed,
>> their `Subtasks` will be passed to `handleComplete`, either in the `FAILED` or
>> `SUCCESS` state. I.e., Unlike `Future`, the state reflects the state of the
>> task itself, not of the handle.
>> 
>> 4. We've added the com.sun.management.Threads.currentThreadEnclosingScopes()
>> method that returns a string with the description of the current structured
>> context -- i.e. the stack trace for the current thread and the enclosing scopes
>> with their owners' respective stack traces -- all the way up the hierarchy.
>> 
>> https://openjdk.org/jeps/453
>> 
>> 
>> -- Ron


More information about the loom-dev mailing list