Structured concurrency: TaskHandle
Remi Forax
forax at univ-mlv.fr
Fri May 12 10:39:42 UTC 2023
I really like the fact that STS.fork() does not return a Future but a TaskHandle because as the JEP [1] said, the idea is to only give accesss to the resulting value (get()) or the exception once join() is called. But I think this approach can be refined following several axis.
1. I believe the method state() should also work like get()/exception(), i.e. if a user call state() before calling join(), an ISE should be thrown.
Practically, it means that state() can not return RUNNING so the enum State can be simplified with only 3 states SUCCESS, FAILED and CANCELLED.
2. I believe CANCELLED is a weird state. First, a lot of other asynchronous libraries merge FAILED and CANCELLED. Then, when shutdown() is called, from a user POV, the corresponding state can be either CANCELLED or FAILED(with an exception InterruptedException). So as a user, getting CANCELLED as result of state() is not enough to know if the task was shutdown or not. I propose to remove the state CANCELLED and usee FAILED + a newly created InterruptedException instead.
3. TaskHandle is a mutable "active object", storing it (by example in a queue) is a common error. TaskHandle should give access to an immutable result object, a record like object that represent SUCCESS (T value) | FAILED(Throwable exception) instead of providing the the methods get()/exception(). With that, handleComplete() should take this result object as parameter instead of TaskHandle so users have less chance to store TaskHandle in a collection.
An interesting followup question is should the TaskHandle objects should be invalidated when close() is called. While it would be nice to have this behavior, it means that it extends the lifetime of the TaskHandle objects so i've rule out that idea.
regards,
Rémi
[1] https://openjdk.org/jeps/8306641#Why-doesn't-fork-return-a-Future?
More information about the loom-dev
mailing list