[External] : Re: Future.resultNow / exceptionNow

Remi Forax forax at univ-mlv.fr
Mon Nov 22 21:36:18 UTC 2021


----- Original Message -----
> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "Alex Otenko" <oleksandr.otenko at gmail.com>
> Cc: "loom-dev" <loom-dev at openjdk.java.net>
> Sent: Lundi 22 Novembre 2021 22:12:38
> Subject: Re: [External] : Re: Future.resultNow / exceptionNow

>> The implementation of a completion policy is spread across two places:
>>
>>  - the handler(s) passed to SE::fork
>>  - the code following the call to SE::join
> 
> I'll add that it is harder to see this because the two policies we've
> specified -- have ad-hoc result states and APIs -- and also have methods
> that fuse state access with side effects.  (In other words, they're
> typical bespoke OO APIs.)  One could imagine a more functional approach,
> where all handlers had a more regularized API:
> 
>     interface Handler<S> {
>         void accept(StructuredExecutor se, Future<?> task);
> 
>         S state();
>     }
> 
> where S would be an algebraic data type (sum of products) representing
> the state.  Then we might define ShutdownOnFailure as implementing
> Handler<SOFStates> where:
> 
>     sealed interface SOFStates {
>         record AllGood() extends SOFStates { }
>         record GotException(Exception e) extends SOFStates { }
>     }
> 
> then using it would look like:
> 
>     try (var executor = SE.open()) {
>         var handler = new ShutdownOnFailure();
> 
>         // forking and joining
> 
>         switch (handler.state()) {
>             case AllGood _ -> return Stream.of(future1, future2)...;
>             case GotException(var e) -> throw new WAE(e);
>        }
>    }
> 
> I'm not suggesting that we do, or don't, redefine the handler API like
> this; I'm offering this as an explanation of why it might have been hard
> to see the relationship between the policy states and the code that
> follows the join.  By regularizing the policy states, we ask handler
> writers/users to engage in some more ceremony (declaring an ADT for
> their state), but regularizing their API and giving users a stronger
> nudge towards proper usage.

You can standardize the API without having the method state() at the interface level.
In your example, you call ShutdownOnFailure::state() not Handler::state().

And why stop at having a method state() on the Handler and not make fork() and join() part of the Handler API too.
It will be a useful simplification because you will be able to merge join() + state() into one method most of the time.

And you can have a specialized version fork() by example to return a Future or not depending on the semantics of the Handler.

Rémi


More information about the loom-dev mailing list