StructureTaskScope joiner naming
David Alayachew
davidalayachew at gmail.com
Thu Sep 25 22:36:47 UTC 2025
Whoops, minor modification.
1. cancelWhen<BiPredicate<R, Subtask<T>>>
On Thu, Sep 25, 2025, 6:34 PM David Alayachew <davidalayachew at gmail.com>
wrote:
> Makes more sense.
>
> You could make a Joiner.Builder class with the following methods.
>
> 1. cancelWhen(Predicate<Subtask<T>>)
> 2. returnValue(R, BiConsumer<R, Subtask<T>>)
> 3. throwWhen(Predicate<Subtask<T>>)
>
> And the absence of any of the above methods has the following default.
>
> 1. Cancel on first Subtask Exception.
> 2. Return all Subtasks as a List.
> 3. Throw the first Subtask Exception.
>
> This gives you the power of permutation, while also give you the Pit of
> Success. Furthermore, you can do away with all of the static methods.
>
> The only weakness is that you leave performance on the table, in some
> cases. Plus, maintaining the Builder gets a little harder, but not by much.
>
>
> On Thu, Sep 25, 2025, 4:58 PM <forax at univ-mlv.fr> wrote:
>
>>
>>
>> ------------------------------
>>
>> *From: *"David Alayachew" <davidalayachew at gmail.com>
>> *To: *"Remi Forax" <forax at univ-mlv.fr>
>> *Cc: *"loom-dev" <loom-dev at openjdk.java.net>
>> *Sent: *Thursday, September 25, 2025 2:47:02 PM
>> *Subject: *Re: StructureTaskScope joiner naming
>>
>> Hello Rémi,
>>
>> > TS.join() always wait, so this is
>> > confusing because a joiner with a
>> > name that does not start with the
>> > name "await" still await.
>>
>> The method name join() makes perfect sense to me -- it joins all the
>> threads.
>>
>> And more accurately, it isn't just waiting, it is joining! Remember that
>> STS with the default semantics (STS.open()) are those that it would have if
>> we did CompletableFuture.allOf().join().
>>
>> Therefore, to base your name off of waiting instead of joining would be
>> the wrong semantics. The method name should remain as join() and should not
>> be called anything else. Especially not await().
>>
>>
>> I think you misunderstood me,
>> i was criticizing the name of the joiners, not the name of STS.join().
>>
>> Some joiners starts with the prefix "await", some don't, but they all
>> wait, because waiting is something done by the STS implementation, not by
>> the joiner implementation.
>>
>> [...]
>>
>>
>>
>> How do you feel about my naming suggestions instead Rémi? I don't have a
>> good replacement for allUntil's name, and I don't want to use cancelWhen,
>> since it throws out the naming convention. But otherwise, how do you feel
>> about it?
>>
>>
>> I obviously prefer mine :)
>> i.e, I think "all" and "await" should not be parts of the name, "await"
>> as discussed above and "all" because the fact that you want all the subtaks
>> whatever their states is a separated concern.
>>
>> Rémi
>>
>>
>> On Thu, Sep 25, 2025 at 2:20 AM Remi Forax <forax at univ-mlv.fr> wrote:
>>
>>> So currently we have those joiner defined in the JDK:
>>> - allSucessfulOrThrow()
>>> - anySucessfulResultOrThrow()
>>> - awaitSucessfulOrThrow()
>>> - awaitAll()
>>> - allUntil(predicate)
>>>
>>> There are several issues,
>>> - TS.join() always wait, so this is confusing because a joiner with a
>>> name that does not start with the name "await" still await.
>>> If you take a look to the doc, the prefix "await" seems to be used to
>>> convey the idea that the result of the STS.join() is null,
>>> i.e the joiner does not stores the forked subtasks in a list.
>>>
>>> - The other issue is the naming of awaitAll(), which is the shorter
>>> name, so people will be droven to use it by default, "it's the simpler",
>>> but unlike the other joiners, it does not cancel the other subtasks in
>>> case of failure, which is not the semantics you want by default.
>>> The name seems to imply that because it does ends with "OrThrow", it
>>> means that there is no cancellation.
>>>
>>> - "allUntil" is a half-lie, it will correctly cancel the other subtask
>>> when one task validates the predicate but at the same time,
>>> STS.join() will returns all subtasks, not the ones until the predicate
>>> is true.
>>> The name "allUntil" only make sense if you see it as the concatenation
>>> of two orthogonal behaviors, "all" meaning STS.join() returns
>>> all subtasks and "until" meaning stop when the predicate is true.
>>>
>>> I propose this renaming (in order):
>>> - allSuccessful()
>>> - anySuccessful()
>>> - sucessfulVoidResult()
>>> - noCancellationVoidResult()
>>> - cancelWhen(predicate)
>>>
>>> After that, i think we can be a little more fancy and see the fact that
>>> the implementation returns all subtasks as a separate concern,
>>> thus enable composition:
>>> - sucessful().all()
>>> - anySucessful()
>>> - sucessful()
>>> - nonCancellation()
>>> - cancelWhen(predicate).all()
>>>
>>> With all() a default method that override onFork() and result() to
>>> respectively add each subtask in a list and blindly returns that list.
>>>
>>> regards,
>>> Rémi
>>>
>>>
>>>
>>>
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20250925/0563fc7e/attachment-0001.htm>
More information about the loom-dev
mailing list