[External] : API proposal for StructuredTaskScope

forax at univ-mlv.fr forax at univ-mlv.fr
Fri Jan 6 21:02:53 UTC 2023


> From: "Ron Pressler" <ron.pressler at oracle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "loom-dev" <loom-dev at openjdk.java.net>
> Sent: Friday, January 6, 2023 8:38:09 PM
> Subject: Re: [External] : API proposal for StructuredTaskScope

>> On 5 Jan 2023, at 15:22, [ mailto:forax at univ-mlv.fr |
>> forax at univ-mlv.fr ] wrote:

>> ----- Original Message -----

>>> From: "Ron Pressler" < [ mailto:ron.pressler at oracle.com |
>>> ron.pressler at oracle.com ] >
>>> To: "Remi Forax" < [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] >
>>> Cc: "loom-dev" < [ mailto:loom-dev at openjdk.java.net | loom-dev at openjdk.java.net
>>> ] >
>>> Sent: Thursday, January 5, 2023 3:37:06 PM
>>> Subject: Re: [External] : API proposal for StructuredTaskScope

>>> We have considered such approaches.

>>> One glaring problem is the case of “heterogenous tasks”, i.e. tasks that each
>>> return a result of a different type. This is a very common scenario for
>>> ShutdownOnFailure.

>> I believe that using a static factory instead of a constructor (here
>> StructuredTaskScope.of()) solve that pretty well.
>> If no type is explicitly provided, the inference will default to Object which is
>> exactly what you want in case of a shutdown on failure.

> I don’t follow. The scenario I had in mind is this:

> Response handle() throws ExecutionException, InterruptedException {
> try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
> Future<String> s1 = scope.fork(() -> fetchS1());
> Future<String> s2 = scope.fork(() -> fetchS2());
> Future<Integer> i1 = scope.fork(() -> fetchI1());
> Future< Integer > i2 = scope.fork(() -> fetchI2());
> scope.join() .throwIfFailed();

> return new Response(s1, s2, i1, i2);
> }
> }

> How do you propose to do it when fork returns void?

Ok, I get it, if the result values are heterogeneous, as you said, fork() has to return a Supplier. 

try(var scope = StructuredTaskScope.of(Reducer.firstException().shutdownOnFailure())) { 
Supplier<Integer> s1 = scope.fork(() -> fetchS1()); 
Supplier<Integer> s2 = scope.fork(() -> fetchS2()); 
Supplier<Integer> i1 = scope.fork(() -> fetchI1()); 
Supplier<Integer> i2 = scope.fork(() -> fetchI2()); 

Optional<Throwable> result = scope.result(); 
result.ifPresent(e -> { throw new RuntimeException(e); }); 
return new Response(s1.get(), s2.get(), i1.get(), i2.get()); 
} 

firstException() returns the first exception as an Optional<Throwable> and shutdownOnFailure() calls shutdown() if there is a failure. 
The nice thing is that shutdownOnFailure() is a composable higern order function that can be used not only with firstException() but with any reducers, like toList() by example. 

> — Ron

Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230106/43666d80/attachment.htm>


More information about the loom-dev mailing list