It looks pretty inconsistent to have the API of the structured concurrency
and of ExtentLocal have different design, especially when it seems like the
2 APIs have the same base assumptions.

>From my understanding those 2 features are meant for each other. I actually
agree that allowing “weak” TwR for ExtentLocals is probably a bad idea, but
I also believe the same for structured concurrency:

    void foo() {
        var scope = new StructuredTaskScope.ShutdownOnFailure();
        var scope1 = new StructuredTaskScope.ShutdownOnFailure();

        scope.close();
        scope1.close();
    }

This should fail on compile time.

This is less important for the incubator, but for the preview I do think it
is important to prevent weird bugs when people misusing the feature.
For example, I can see someone without understanding of structured
concurrency writing the following:

// abstraction of a calculation on "int[]" that can be partitioned and
then aggregated into a single result// contains "int set/setCount()"
for the count of partitions, a method "void calcPart(int[] lst, int
partNumber)", "void aggregateParts()" and "int getResult()"public
interface PartitiableAction { ... }
...public static void calcAtOnce(Collection<PartitiableAction>
actions, int[] input) {
   var scopes = new HashMap<PartitiableAction,
StructuredTaskScope.ShutdownOnFailure>();
   // start a scope for each action
   for (var action : actions) {
       var scope = new StructuredTaskScope.ShutdownOnFailure();
        scopes.put(action, scope);
         // new thread for each part of the calculation
        for (var j = 0; j < action.getCount(); j++)  scope.fork(() =>
 action.calcPart(input, j));
   }

   // !! Undefined behavior !!
   for (var action : actions) {
         var scope = scopes.get(action);
         scope.join();
         action.aggregateParts();
         scope.close();
    }

}

Some implementations of Collection that will always fail, some will always
succeed, and some implementations (like HashSet) may be non-deterministic.
For the uninformed this method makes sense, for each PartitiableAction I
create some kind of a new “Executor“ that everyone is talking about, if one
of the parts fails, the whole calculation of this specific PartitiableAction
will stop running, and I am waiting for everything to end.
------------------------------

I can write a PoC compiler plugin such that classes with @StrongTwR
annotation can only be assigned inside TwR (unless they are also the return
value) (I will probably do it tomorrow and send a link to it in a follow up
mail if people are interested)

On Thu, Aug 4, 2022 at 11:51 AM Andrew Haley <aph-o...@littlepinkcloud.com>
wrote:

> On 7/29/22 21:37, Ron Pressler wrote:
> > Yes, we are thinking about a "strong” TwR, but we’re busy with so many
> things so it might take a while. Until then, we might introduce a weaker,
> or less trustworthy version of ExtentLocals that uses the existing TwR and
> wouldn’t be used for critical things, but we think that it’s best to start
> incubation with just the lambda API and then see what problems are most
> common/annoying and how we can best address them.
>
> One of the worst problems with using "weak" TWR for extent locals is that
> ensuring the invariants with respect to structured concurrency is hard.
> You end up with complex consistency checks that must be checked at runtime,
> and are hard to test.
>
> --
> Andrew Haley  (he/him)
> Java Platform Lead Engineer
> Red Hat UK Ltd. <https://www.redhat.com>
> https://keybase.io/andrewhaley
> EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
>


-- 
Holo The Wise Wolf Of Yoitsu

Reply via email to