[External] : Re: A new build and a new structured concurrency API
Alan Bateman
Alan.Bateman at oracle.com
Tue Nov 16 14:26:13 UTC 2021
On 16/11/2021 13:51, forax at univ-mlv.fr wrote:
> :
> I've decided to focus on the high-level API first.
> I agree that separating the low-level API and allow anyone to create more high level APIs is a good design.
> For me the low-level API which is almost synonymous of StructuredExecutor.
>
> Do we agree that ShutdownOnSuccess/ShutdownOnFailure are examples of the kind of high level APIs that can be written ?
>
> I believe that passing the StructuredExecutor at construction helps to solve several issues.
> As i said, it ties a little more the lifecycle of the Handler policies to the lifecycle of the StructuredExecutor.
> It also allows to avoid to have a method accept() to be part of the public API (see below).
> There is also no problem to use several policies with each one taking the same StructuredExecutor.
> It's less flexible than the current API because you can share a policy handler between several different StructuredExecutors but i see that more as something bug prone than as a feature.
>
> Currently, the API is creates from two parts,
> StructuredExecutor.fork(Callable, BiConsumer)
> and
> BiConsumer.accept(StructuredExecutor, Future)
>
> For me, this handshake should be secret and not part of the public API given that
> - StructuredExecutor.fork(Callable, BiConsumer) should not be part of the public API because users should either use the variant without a BiConsumer or use the BiConsumer/Handler API which can be better tailored to the use case the policy handler want to solve
> - BiConsumer.accept(StructuredExecutor, Future) should not be part of the public API because users don't care at all about how this is implemented.
>
> By example with a SPI, that make StructuredExecutor.fork(Callable, BiConsumer) non visible in StructuredExecutor
> public class StructuredExecutorSPI {
> public static <V> Future<V> fork(StructuredExecutor executor, Callable<? extends V> callable, Consumer<? super Future<V>> completerConsumer) {
> return ...
> }
> }
>
>
> ShutdownOnSuccess can be written like this:
>
> public class ShutdownOnSuccess<V, X extends Exception> {
> private final StructuredExecutor executor;
>
> public ShutdownOnSuccess(StructuredExecutor executor) {
> this.executor = executor;
> }
>
> public Future<V> fork(CallableWithException<V, X> task) {
> return StructuredExecutorSPI.fork(executor, task::call, future -> {
> // do something with the executor and the future
> });
> }
>
> ...
> }
You've addressed a potential misuse but your sketch means that 4 classes
define a fork method. We've been trying to keep it simple with the fork
methods in one place. Where you need something other than ShutdownOnXXX
then it's easy to implement a BiConsumer without needing to introduce
another interface/class for implementations.
I've no doubt that the API will go through several iterations. I think
we need to some usage before doing another iteration.
-Alan.
More information about the loom-dev
mailing list