[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