<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Hi Adam,<br>
<br>
First of all, thanks for reaching out with thoughts, comments, and general feedback on your use of Structured Concurrency—it is much appreciated!<br>
<br>
Some thoughts and comments below:<br>
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>1) SCS works great when tasks are independent, and known upfront; that is, when tasks aren’t dynamically generated based on computations that are part of the scope.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
I think I understand what you intend to say, but I think more specifically you're referring to when tasks are generated as a result of
<i>*other tasks*</i>, not the scope body itself.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Case in point:</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
try(var scope = …) {</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
while(dynamicCondition) // Dynamic number of tasks</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
scope.fork(…);</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
scope.join();</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
}</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>someone on Reddit already pointed out that a better implementation using SCS nested scopes exists.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
When in doubt, consider if nested scopes could make the design clearer. This is analoguous to breaking a large, complex, method-body down into multiple smaller ones.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>Still, if we add requirements around rate limiting, per-domain connection pooling etc., a solution with a centralised coordinator becomes more viable.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Not sure how that conclusion was derived. Could you explain further?</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>Other examples might include implementing an actor-like component, where the actor’s body becomes the scope's body, handles some private (mutable) state, and communicates with child processes (forks created in the scope) using queues.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Inter-task communication channels are not part of Structure Concurrency at this point in time. It is however important to note that StructuredTaskScope is not the end state of Structured Concurrency.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>If the main scope body includes any blocking logic, it might end up hanging indefinitely, while all the other forks have been cancelled.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
That statement is true by definition—any code which is blocking indefinitely and is not interrupted, is by definition blocking indefinitely. </div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>The main scope’s body awaits for data from either of them (on a queue), and when an element is produced, sends it downstream. Now, if we’re not careful with error handling, an exception in one of the substreams will cancel the scope, but the main scope will
indefinitely wait on data, not aware of the error.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
This sounds, to me, like another issue with an absent feature—Inter-task communication channels.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>Moreover, I allow creating forks-in-forks, so that the main logic can create forks at will.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
As this is described, this means that you could have a race condition between forking in the same scope and the call to scope.join(), or did I misunderstand?</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>My work-around here is to create a `Joiner` which monitors an `isDone` flag, and submit an empty task after the work is determined to be done:</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Since Joiners are one-shot, and are created before the scope is opened, it would seem more logical(?) to embed that flag into the joiner and have it be set by the scope body by referring to the joiner:</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
var myJoiner = new MyJoiner(…);</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
try(var scope = StructuredTaskScope.open(myJoiner)) {</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
…</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
myJoiner.signalDone()</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
scope.join();</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
}</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>But it’s more of an ugly trick, rather than a proper solution. I think the essence of the problem is that the logic of the scope is divided between the scope body, and the `Joiner` implementation, and it’s hard to keep them in sync.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
«Designing a Joiner should take into account the code at the use-site where the results from the join method are processed. It should be clear what the Joiner does vs. the application code at the use-site. In general, the Joiner implementation is not the place
for "business logic". A Joiner should be designed to be as general purpose as possible.» - https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/StructuredTaskScope.Joiner.html</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
>Special-casing for this seems odd, as timeout is only one example from a family of "resiliency" methods, others including retries, repeats etc. These as well, could be implemented on top of virtual threads and SCS as methods, without special support from the
SCS API itself.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
While it is true that the I combinator, in SKI calculus, is not primitive because it can be implemented in terms of the S and K combinators, that doesn't necessarily mean that we should strive to distill the absolute primitives. There also exists a scientific
paper on the Turing Completeness of the x86 MOV instruction—but it's Turing Completeness does not rule out the value of having specialized instructions.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Putting a deadline on a concurrent operation is established "good practice" to ensure liveness, and the duration for that timeout is most useful if it is provided by the caller, so creating a standardized configuration option for this common operation was deemed
to be worth it, since we do not need to either create a scope-within-a-scope by default or filter out the Subtask handling the timeout.</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
> The Subtask.get() method is confusing</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
«public static sealed interface StructuredTaskScope.Subtask<T></div>
<div style="line-height: 18px; font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
extends Supplier<T>» - https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/StructuredTaskScope.Subtask.html</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
All the best!</div>
<div class="elementToProof" id="Signature">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Cheers,<br>
√</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<b><br>
</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<b>Viktor Klang</b></div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> loom-dev <loom-dev-retn@openjdk.org> on behalf of Adam Warski <adam@warski.org><br>
<b>Sent:</b> Friday, 26 September 2025 08:37<br>
<b>To:</b> loom-dev@openjdk.org <loom-dev@openjdk.org><br>
<b>Subject:</b> Problem report on the usage of Structured Concurrency (5th preview)</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Good morning,<br>
<br>
with the release of Java 25, I’ve attempted to migrate my virtual-thread-native, reactive-streaming-like library from Java 21 to Java 25 scopes. So far I’ve been using my own wrapper on StructuredConcurrencyScope, but with that migration I wanted to eliminate
it, and just use SCS directly. However, I encountered some problems with SCS’s design; I've summarised them in a blog (<a href="https://softwaremill.com/critique-of-jep-505-structured-concurrency-fifth-preview">https://softwaremill.com/critique-of-jep-505-structured-concurrency-fifth-preview</a>),
and then prompted by a discussion on Reddit that followed (<a href="https://www.reddit.com/r/java/comments/1nq25yr/critique_of_jep_505_structured_concurrency_fifth/">https://www.reddit.com/r/java/comments/1nq25yr/critique_of_jep_505_structured_concurrency_fifth/</a>),
I’m writing here.<br>
<br>
Here’s a summary of the issues:<br>
<br>
1) SCS works great when tasks are independent, and known upfront; that is, when tasks aren’t dynamically generated based on computations that are part of the scope. In that case, some communication between the forks & the main scope body is needed - typically
using queues. The example I give in the article is of a web crawler, however it might not be the best one, as someone on Reddit already pointed out that a better implementation using SCS nested scopes exists. Still, if we add requirements around rate limiting,
per-domain connection pooling etc., a solution with a centralised coordinator becomes more viable. Other examples might include implementing an actor-like component, where the actor’s body becomes the scope's body, handles some private (mutable) state, and
communicates with child processes (forks created in the scope) using queues.<br>
<br>
Such a centralised coordinator (implemented as the scope’s body) does not, however, participate in the error handling contract of the forks. If there’s an exception in the forks, (using the default Joiner) the scope will be cancelled, and all other forks will
be interrupted - and that’s of course correct. However, the main scope body won’t be (and it can’t be, as the interruption could escape the scope). If the main scope body includes any blocking logic, it might end up hanging indefinitely, while all the other
forks have been cancelled.<br>
<br>
To make the problem a little bit more concrete, I encountered the above (and problem number 2 as well) when implementing Jox (<a href="https://github.com/softwaremill/jox">https://github.com/softwaremill/jox</a>) `Flow` stages. For example, when merging two
streams, the merged substreams need to be run in the background, concurrently, within a concurrency scope. The main scope’s body awaits for data from either of them (on a queue), and when an element is produced, sends it downstream. Now, if we’re not careful
with error handling, an exception in one of the substreams will cancel the scope, but the main scope will indefinitely wait on data, not aware of the error.<br>
<br>
I’m currently solving this by still having my custom wrapper on top of scopes. The wrapper essentially provides custom concurrency scopes, which run the main scope logic in a fork, making it participate in the error handling/cancellation properties of all other
forks. Moreover, I allow creating forks-in-forks, so that the main logic can create forks at will.<br>
<br>
2) If the scope’s body does include some non-trivial coordination logic, then it should also be able to decide that a scope is "done". My example here is that there might be two kinds of forks: some implementing the actual logic, and some serving "helper" functions.
Following the crawling example, the main-logic forks would be the crawlers; helper forks could e.g. implement monitoring. Now, when the coordinator (main scope body) decides that the computation is done, the scope should be completed, cancelling any helper
forks. Currently this can be implemented through a `Joiner`. However, if the data needed to decide, if a scope should complete is present in the coordinator (scope body), it’s problematic to pass that information to the `Joiner`. My work-around here is to
create a `Joiner` which monitors an `isDone` flag, and submit an empty task after the work is determined to be done:<br>
<br>
void main() throws ExecutionException, InterruptedException {<br>
var isDone = new AtomicBoolean(false);<br>
try (var scope = StructuredTaskScope.open(<br>
new CancellableJoiner<>(isDone))) {<br>
// some logic<br>
<br>
isDone.set(true);<br>
scope.fork(() -> {});<br>
<br>
scope.join();<br>
}<br>
}<br>
<br>
class CancellableJoiner<T> <br>
implements StructuredTaskScope.Joiner<T, Void> {<br>
<br>
private final AtomicBoolean isDone;<br>
CancellableJoiner(AtomicBoolean isDone) { this.isDone = isDone; }<br>
<br>
public boolean onFork(<br>
StructuredTaskScope.Subtask<? extends T> subtask) {<br>
return isDone.get();<br>
}<br>
<br>
// ...<br>
}<br>
<br>
But it’s more of an ugly trick, rather than a proper solution. I think the essence of the problem is that the logic of the scope is divided between the scope body, and the `Joiner` implementation, and it’s hard to keep them in sync.<br>
<br>
3) The final two problems are more of nitpicks. First, a `timeout` method can easily be implemented using the machinery of the SCS, without additional configuration parameters. Special-casing for this seems odd, as timeout is only one example from a family
of "resiliency" methods, others including retries, repeats etc. These as well, could be implemented on top of virtual threads and SCS as methods, without special support from the SCS API itself.<br>
<br>
4) The Subtask.get() method is confusing, as it has the semantics of Future.resultNow(), but the nomenclature of Future.get(). Since Future.get() is quite well established, I think it’s reasonable to assume, without prior knowledge of the SCS API, that Subtask.get()
is blocking as well. However, it works rather differently. I understand that .get() is a fitting name, however given the existing functionalities in place, I would consider changing the name to something without naming or semantical clashes.<br>
<br>
----<br>
<br>
One might say, that my requirements are above regular use-cases for SCS. However, I view SCS as the new base building block for IO-bound concurrency in Java, and that any future concurrency libraries or projects should use it. This is supported by the fact
that `ScopedValue`s are only inherited within SCSs - and I think any concurrency library or feature should provide such propagation. Hence, it should build on top of SCS. That’s why I’m seeking how to make SCS more flexible, to accommodate also for the more
unusual or advanced use-cases.<br>
<br>
Thank you for your work on SCS and Virtual Threads! I think what’s currently there is really great and powerful, even if not (yet) perfect :).<br>
<br>
Regards,<br>
Adam Warski<br>
<br>
-- <br>
Adam Warski<br>
<br>
<a href="https://warski.org">https://warski.org</a><br>
<a href="https://twitter.com/adamwarski">https://twitter.com/adamwarski</a><br>
<br>
</div>
</span></font></div>
</body>
</html>