Business policy inside a StructuredTaskScope

Remi Forax forax at univ-mlv.fr
Mon Sep 11 21:55:27 UTC 2023


> From: "David" <david.vlijmincx at gmail.com>
> To: "loom-dev" <loom-dev at openjdk.org>
> Sent: Monday, September 11, 2023 11:07:59 PM
> Subject: Business policy inside a StructuredTaskScope

> Hi,

> I have a question about where the business logic / shutdown policy is supposed
> to be when you extend from a StructuredTaskScope. Looking at online examples it
> seems like the business logic is supposed to be in the handleComplete method of
> a class that extends StructuredTaskScope, but is this not too far away from the
> place it is being used?
> Currently, I am using the following scope as it keeps the shutdown policy closer
> to where the scope is used in my code, but I do not know if this is the correct
> way of creating your own scopes.

> class TriggerScope < T > extends StructuredTaskScope < T > {

> final private Function < StructuredTaskScope . Subtask <? extends T >, Boolean >
> trigger ;

> TriggerScope ( Function < StructuredTaskScope . Subtask <? extends T >, Boolean
> > trigger) {
> this . trigger = trigger;
> }

> @Override
> protected void handleComplete ( Subtask <? extends T > subtask) {
> if ( trigger .apply(subtask)) {
> shutdown();
> }
> }
> }
> The above scope allows me to implement a new scope like below:
> public static void main ( String [] args) throws InterruptedException {

> Main main = new Main();

> try ( var scope = new TriggerScope< Product >( main ::trigger)) {

> StructuredTaskScope . Subtask < Product > fork = scope .fork(() -> new Product(
> 50 ));
> StructuredTaskScope . Subtask < Product > fork1 = scope .fork(() -> new Product(
> 100 ));
> StructuredTaskScope . Subtask < Product > fork2 = scope .fork(() -> new Product(
> 150 ));

> scope .join();
> }

> }

> private boolean trigger ( StructuredTaskScope . Subtask <? extends Product >
> subtask) {
> if ( Subtask . State . SUCCESS .equals(subtask.state()) && subtask.get().price()
> > 50 && subtask.get().price() < 150 ){
> System . out .println( "result: " + subtask.get().price());
> return true ;
> }
> return false ;
> }

> In my opinion, this way is more convenient, but is this still a correct
> implementation or does this deviate too much from the original idea of creating
> a scope in its own class?

> Looking forward to hearing your thoughts.

It is Ok but a little dangerous if you start to add fields to the Main object to retrive the price instead of printing it, perhaps it's better to declare tigger static and use Main::trigger instead of main::trigger. 

In term of code, State.Sucess is an enum value so you can use == to compare it with the state, instead of calling subtasl.get().price() several times you can store it in a local variable and trigger should be typed as a Predicate (a function that return a boolean). 

Now, i agree with you that storing the business logic iside the STS is a king of ugly. 
That's why I want to add a STS that see the tasks as a stream, to avoid to store the business logic inside a STS, here is your code rewritten using a Streamable STS. 

static boolean isValid(Subtask<Product> task) { 
if (task.state() != SUCCESS) { 
return false; 
} 
var price = task.get().price(); 
return price > 50 && price < 150; 
} 
... 
Optional<Product> resultingProduct; 
try(var scope = new StructuredTaskScope.Streamable<Product>>()) { // need a better name 
scope.fork(() -> new Product(50)); 
scope.fork(() -> new Product(100)); 
scope.fork(() -> new Product(150)); 
resultingProduct = scope.joinWhile(stream -> stream.filter(Utils::isValid).map(Subtask::get).findFirst()); 
} 

This code can also be written with one mapMulti() instead of filter() + map(), but given that not a lot of people known how mapMulti() works, i've preferred to write this version. 

> Kind regards,
> David

regards, 
Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230911/7e045ef0/attachment-0001.htm>


More information about the loom-dev mailing list