[External] : Re: Future.resultNow / exceptionNow
Brian Goetz
brian.goetz at oracle.com
Mon Nov 22 21:12:38 UTC 2021
> 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.
More information about the loom-dev
mailing list