<div dir="ltr"><div>Just a drive-by comment...</div><div><br></div><div>I agree with Victor about being careful about making any API/semantic changes. However, I also have a lot of sympathy for what is being asked for.</div><div><br></div><div>A common pattern is to want to say, "Try doing these N things in parallel; if any of them fails, just bail out - immediately cancel all of them and throw an exception".</div><div><br></div><div>In other words, in a particular scenario you are expecting perfection, and if anything less occurs, it's preferable to just completely give up. Trying to salvage it is not worth it.</div><div><br></div><div>So it would be nice if there were some parallel stream map() variant with those semantics (it could also preserve order, but that seems orthogonal).</div><div><br></div><div>-Archie</div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Mon, Oct 6, 2025 at 9:59 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com">viktor.klang@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="msg4625441815577589225">




<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi Jige,<br>
<br>
I'm not sure it's productive to discuss the in-order behavior of mapConcurrent() further, as it is specified to be in-order, so changing that would be an incompatible change regardless of whether the change itself would be beneficial or not.</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
For potential future Gatherer-implementations made available from the Gatherers class, there'd need to be new implementations made available which over time prove themselves to be candidates for inclusion (also taking into consideration everything which comes
 with contributing code to OpenJDK).</div>
<div id="m_4625441815577589225Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="text-align:left;margin-left:5pt;font-family:Calibri;font-size:10pt;color:rgb(0,0,0)">
Confidential – Oracle Internal</div>
</div>
<div id="m_4625441815577589225appendonsend"></div>
<hr style="display:inline-block;width:98%">
<div id="m_4625441815577589225divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Sunday, 5 October 2025 19:06<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Question about mapConcurrent() Behavior and Happens-Before Guarantees</font>
<div> </div>
</div>
<div>
<div dir="ltr">
<p>Hi Viktor,</p>
<p>Thanks again for explaining the current in-order contract. While I understand the implementation is currently compliant with the Javadoc, I have a few additional concerns about the practical consequences of this delayed exception propagation.</p>
<p></p>
<h2><span style="font-weight:normal">Potential for Starvation</span></h2>
<p></p>
<p>While in theory it's also a lack of fail fast, it may show up more like a <b>starvation or system hangs</b> in certain concurrent architectures.</p>
<p>Imagine a scenario where the virtual threads are consuming work items from a shared, blocking queue (like what's being discussed in the other thread, the virtual threads could themselves be producing data into the queue):</p>
<ol start="1">
<li>
<p>Task 3 successfully takes an item from the queue and then immediately fails with an exception, without producing any data into the queue.</p>
</li><li>
<p>Tasks 1 and 2 block on the queue to get their work items, <b>indefinitely</b>.</p>
</li><li>
<p>Because the exception from Task 3 is not propagated until Tasks 1 and 2 finish, the main thread or stream pipeline is blocked indefinitely if Tasks 1 or 2 hang.</p>
</li><li>
<p>The work item consumed by Task 3 is lost, and the system is effectively halted, as the failure isn't reported and cleanup/cancellation is delayed.</p>
</li></ol>
<p>So, except performance hit; it creates stability and liveness issues.</p>
<hr>
<p></p>
<h2><span style="font-weight:normal">Ambiguity in Current Javadoc</span></h2>
<p></p>
<p>Regarding the Javadoc, while I did read it, I found the lack of an explicit fail-fast guarantee and the precise timing of exception propagation to be subtle. The phrase,
<b>"If a result of the function is to be pushed downstream,"</b> seems to leave ample room for interpretation, and it was not immediately clear whether the lack of fail-fast was an intentional design choice versus a side effect of the in-order implementation.
 Clarifying this timing can probably improve the API's contract clarity.</p>
<hr>
<p></p>
<h2><span style="font-weight:normal">Re-evaluating the "In-Order" Contract</span></h2>
<p></p>
<p>Apologies for circling back to the same "in-order" question that has already been discussed.</p>
<p>But from a usability perspective, I suggest we also bring the <b>"in-order" contract itself</b> up for discussion.</p>
<p>I believe that the issues we've identified—the potential for starvation/hanging and the earlier discussed concurrency throughput concerns—are significant, realistic downsides of requiring strict in-order processing. These drawbacks should be carefully weighed
 against the benefits of the "in-order" contract, especially for concurrent processing APIs intended for I/O-bound tasks where strict ordering often has minimal value compared to resilience and performance.</p>
<p>If it's a trade off between having <b>in-order or fail-fast</b> (but not both simultaneously), it may warrant some more consideration about which is more useful. Particularly, Java users have traditionally been educated that parallel streams don't necessarily
 retain encounter order.</p>
<p>Cheers,</p>
</div>
<br>
<div>
<div dir="ltr">On Sun, Oct 5, 2025 at 2:13 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>> wrote:<br>
</div>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi Jige,<br>
<br>
Thanks for your question!<br>
<br>
It is important to acknowledge that Gatherers.mapConcurrent() does not specify fail-fast behavior.<br>
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>From <a id="m_4625441815577589225x_m_-1776469347706997007LPlnk370475" href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)" target="_blank">
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)</a></div>
<div id="m_4625441815577589225x_m_-1776469347706997007Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<i>"In progress tasks will be attempted to be cancelled, on a best-effort basis, in situations where the downstream no longer wants to receive any more elements."</i> </div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
This does not refer to failed tasks</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<i>"If a result of the function is to be pushed downstream but instead the function completed exceptionally then the corresponding exception will instead be rethrown by this method as an instance of
</i><span style="font-family:"DejaVu Sans Mono",monospace;color:rgb(67,114,145)"><i><code style="font-family:"DejaVu Sans Mono",monospace"><a title="class in java.lang" id="m_4625441815577589225x_m_-1776469347706997007OWA7c0b4b0e-7586-1356-59f7-96f38ee3f3f4" href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/RuntimeException.html" style="color:rgb(67,114,145);text-align:left" target="_blank">RuntimeException</a></code></i></span><i>,
 after which any remaining tasks are canceled."</i></div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Since mapConcurrent is in-order, "is to be pushed downstream" means that it is next in line.</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Now, I'm not saying that fail-fast wouldn't be desirable behavior, but it would require research into how to implement it without breaking observable behavior.</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="text-align:left;margin-left:5pt;font-family:Calibri;font-size:10pt;color:rgb(0,0,0)">
Confidential – Oracle Internal</div>
</div>
<div id="m_4625441815577589225x_m_-1776469347706997007appendonsend"></div>
<hr style="display:inline-block;width:98%">
<div id="m_4625441815577589225x_m_-1776469347706997007divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Sunday, 5 October 2025 07:10<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Question about mapConcurrent() Behavior and Happens-Before Guarantees</font>
<div> </div>
</div>
<div>
<div dir="ltr">Hi, Viktor.
<div><br>
</div>
<div>I recently suggested mapConcurrent() for a concurrent web crawling use case. But I was presented with a test case that showed surprising results. Basically, the current behavior may look like mapConcurrent() doesn't fail fast, and doesn't cancel in-flight
 tasks when a task has already failed.</div>
<div><br>
</div>
<div>What actually happens in the following example is that the first two tasks are sleeping, while the 3rd task has already failed. But mapConcurrent() doesn't yet know that the 3rd task has failed until the first two tasks have successfully finished sleeping.</div>
<div><br>
</div>
<div>Here's the test case:</div>
<div><br>
</div>
<div>
<div style="padding:0px 0px 0px 2px">
<div style="color:rgb(0,0,0);font-family:Menlo;font-size:12pt;white-space:pre-wrap">
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">int</span> work(<span style="color:rgb(127,0,85);font-weight:bold">int</span>
<span style="color:rgb(106,62,62)">input</span>) {</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">if</span> (<span style="color:rgb(106,62,62)">input</span> <= 2) {</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">try</span> {</p>
<p style="margin:0px">IO.<span style="font-style:italic">println</span>(<span style="color:rgb(106,62,62)">input</span> +
<span style="color:rgb(42,0,255)">" sleeping "</span>);</p>
<p style="margin:0px">Thread.<span style="font-style:italic">sleep</span>(2000);</p>
<p style="margin:0px">IO.<span style="font-style:italic">println</span>(<span style="color:rgb(42,0,255)">"Returning "</span> + (<span style="color:rgb(106,62,62)">input</span> * 2));</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">return</span>
<span style="color:rgb(106,62,62)">input</span> * 2;</p>
<p style="margin:0px">} <span style="color:rgb(127,0,85);font-weight:bold">catch</span> (InterruptedException
<span style="color:rgb(106,62,62)">e</span>) {</p>
<p style="margin:0px"><span style="font-style:italic">println</span>(<span style="color:rgb(42,0,255)">"Interrupted!"</span>);</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">throw</span>
<span style="color:rgb(127,0,85);font-weight:bold">new</span> RuntimeException(<span style="color:rgb(106,62,62)">e</span>);</p>
<p style="margin:0px">}</p>
<p style="margin:0px">} <span style="color:rgb(127,0,85);font-weight:bold">else</span> {</p>
<p style="margin:0px">IO.<span style="font-style:italic">println</span>(<span style="color:rgb(106,62,62)">input</span> +
<span style="color:rgb(42,0,255)">" Throwing"</span>);</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">throw</span>
<span style="color:rgb(127,0,85);font-weight:bold">new</span> RuntimeException();</p>
<p style="margin:0px">}</p>
<p style="margin:0px">}</p>
<p style="margin:0px"><br>
</p>
<p style="margin:0px"><span style="color:rgb(100,100,100)">@Test</span> <span style="color:rgb(127,0,85);font-weight:bold">
public</span> <span style="color:rgb(127,0,85);font-weight:bold">void</span> mainTest() {</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">var</span>
<span style="color:rgb(106,62,62)">start</span> = System.<span style="font-style:italic">currentTimeMillis</span>();</p>
<p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">try</span> {</p>
<p style="margin:0px">List<Integer> <span style="color:rgb(106,62,62)">results</span> = Stream.<span style="font-style:italic">of</span>(1, 2, 3).gather(<span style="font-style:italic">mapConcurrent</span>(3,
<span style="color:rgb(127,0,85);font-weight:bold">this</span>::work)).toList();</p>
<p style="margin:0px"><span style="font-style:italic">println</span>(<span style="color:rgb(42,0,255)">"Results = "</span> +
<span style="color:rgb(106,62,62)">results</span>);</p>
<p style="margin:0px">} <span style="color:rgb(127,0,85);font-weight:bold">finally</span> {</p>
<p style="margin:0px"><span style="font-style:italic">println</span>(<span style="color:rgb(42,0,255)">"Took "</span> + (System.<span style="font-style:italic">currentTimeMillis</span>() -
<span style="color:rgb(106,62,62)">start</span>) + <span style="color:rgb(42,0,255)">
" ms"</span>);</p>
<p style="margin:0px">}</p>
<p style="margin:0px">}</p>
</div>
</div>
</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
</div>
<br>
<div>
<div dir="ltr">On Mon, Jul 14, 2025 at 12:25 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>> wrote:<br>
</div>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi Jige,</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
The current behavior is what's currently achievable within the constraints of the Gatherer-model, if that changes in the future it would also mean that there could be stronger "guarantees" made.</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
In the mean time, the good news is that if you're not satisfied with the behavior offered by mapConcurrent()—you can create your own which does what you want it to do!</div>
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960appendonsend"></div>
<hr style="display:inline-block;width:98%">
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960divRplyFwdMsg" dir="ltr">
<font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Sunday, 13 July 2025 05:54<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Re: [External] : Re: Question about mapConcurrent() Behavior and Happens-Before Guarantees</font>
<div> </div>
</div>
<div>
<div dir="ltr">Thanks for pressing on that, Viktor!
<div><br>
</div>
<div>I think I was fooled by my quick-and-dirty test. As I tried to harden it, I failed to deduce consistent behavior about what parallel stream does when unchecked exceptions happen. And in fact, it seems like it does *not* interrupt pending threads (?).</div>
<div><br>
</div>
<div>With this in mind, do you consider this behavior of mapConcurrent() cancelling and joining the virtual threads on a best-effort basis acceptable trade-off?</div>
<div><br>
</div>
<div>I wonder then if it's even worth it for mapConcurrent() to try to join the threads at all? If it can sometimes join and sometimes not, why not just always fail fast? At least then you get consistent fail-fast behavior: if a thread fails to respond to interruption
 and hangs, the main thread would still be able to respond to the exception.</div>
<div><br>
</div>
<div>Cheers,</div>
<div><br>
</div>
<div><br>
</div>
</div>
<br>
<div>
<div dir="ltr">On Tue, Jul 8, 2025 at 2:34 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>> wrote:<br>
</div>
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>I understand that explicit API contracts are what matters. My concern, however, is that even if the API contract explicitly states
<i>no</i> happens-before guarantee upon an unchecked exception, this behavior would still be a significant deviation from established visibility standards in other JDK APIs.</div>
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397Signature">
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Would you mind clariying <i>exactly</i> what you mean here—<b>what</b> happens-before completion/exception?</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397appendonsend">
</div>
<div style="font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<hr style="display:inline-block;width:98%">
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Tuesday, 8 July 2025 04:26<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> [External] : Re: Question about mapConcurrent() Behavior and Happens-Before Guarantees</div>
<div style="direction:ltr"> </div>
</div>
<div style="direction:ltr">Thanks for the quick reply, Viktor!</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Mon, Jul 7, 2025 at 2:35 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397OWA03733348-faf5-1f9c-7469-0fc114618627" target="_blank">viktor.klang@oracle.com</a>>
 wrote:</div>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Hi Jige,</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
>Initially, I thought this design choice might provide a strong happens-before guarantee. My assumption was that an application catching a
<code>RuntimeException</code> would be able to <b>observe all side effects</b> from the virtual threads, even though this practice is generally discouraged. This seemed like a potentially significant advantage, outweighing the risk of a virtual thread failing
 to respond to interruption or responding slowly.</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Unless explicitly stated in the API contract, no such guarantees should be presumed to exist.</div>
</blockquote>
<div style="direction:ltr"><br>
</div>
<p style="direction:ltr">I understand that explicit API contracts are what matters. My concern, however, is that even if the API contract explicitly states
<i>no</i> happens-before guarantee upon an unchecked exception, this behavior would still be a significant deviation from established visibility standards in other JDK APIs.</p>
<p style="direction:ltr">For instance, both <b>parallel streams</b> and <code>Future.get()</code> provide a happens-before guarantee upon completion (or exceptional completion in the case of
<code>Future.get()</code>). So users will most likely take it for granted. If <code>
mapConcurrent()</code> were to <i>not</i> offer this, it would potentially be the
<b>first blocking JDK API that doesn't honor happens-before</b> in such a scenario. This inconsistency would likely be surprising and potentially confusing to users who have come to expect this behavior in concurrent programming constructs within the JDK.</p>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
As for general resource-management in Stream, I have contemplated designs for Gatherer (and Collector) to be able to participate in the onClose actions, but there's a lot of ground to cover to ensure correct ordering and sufficiently-encompassing of cleanup
 action execution.</div>
</blockquote>
<div style="direction:ltr"><br>
</div>
<p style="direction:ltr">Yeah. I agree that hooking into <code>onClose()</code> could provide a more reliable mechanism for cleanup.</p>
<p style="direction:ltr">My primary concern though, is the change it imposes on the call-site contract. Requiring all users of
<code>mapConcurrent()</code> to adopt a <code>try-with-resources</code> syntax, while ideal for correctness, introduces a burden and is more subject to users forgetting to do so, potentially leading to resource leaks.</p>
<p style="direction:ltr">My previously proposed <code>collectingAndThen(toList(), list -> list.stream().gather(mapConcurrent()))</code> idea, on the other hand, avoids this call-site contract change. Being a collector, it needs to first consume the input, similar
 to how most <code>Collector</code>s operate. So it might be a less intrusive path to ensure proper resource handling without altering usage patterns.</p>
<blockquote style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left:1px solid rgb(204,204,204)">
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397x_m_3888783633770680312Signature">
<div style="direction:ltr;font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Cheers,<br>
√</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<br>
</div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b><br>
</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<b>Viktor Klang</b></div>
<div style="direction:ltr;font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
Software Architect, Java Platform Group<br>
Oracle</div>
</div>
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397x_m_3888783633770680312appendonsend">
</div>
<hr style="direction:ltr;display:inline-block;width:98%">
<div id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397x_m_3888783633770680312divRplyFwdMsg">
<div style="direction:ltr;font-family:Calibri,sans-serif;font-size:11pt;color:rgb(0,0,0)">
<b>From:</b> core-libs-dev <<a href="mailto:core-libs-dev-retn@openjdk.org" id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397OWA9a0f1614-0d0e-45ff-bf44-ac9d53989e80" target="_blank">core-libs-dev-retn@openjdk.org</a>> on behalf of
 Jige Yu <<a href="mailto:yujige@gmail.com" id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397OWA665e320d-1bba-87cf-926a-de0761f52291" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Thursday, 3 July 2025 16:36<br>
<b>To:</b> <a href="mailto:core-libs-dev@openjdk.org" id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397OWA9e722186-0c4f-3c81-ee03-46462c9ec9bf" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="m_4625441815577589225x_m_-1776469347706997007x_m_-6926773055309159960x_m_6567895471522507397OWA4899b1d3-1eb1-020f-c1ea-a1e4f2797e52" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> Question about mapConcurrent() Behavior and Happens-Before Guarantees</div>
<div style="direction:ltr"> </div>
</div>
<p style="direction:ltr">Hi JDK Core Devs,</p>
<p style="direction:ltr">I'm writing to you today with a question about the behavior of
<code>mapConcurrent()</code> and its interaction with unchecked exceptions. I've been experimenting with the API and observed that
<code>mapConcurrent()</code> blocks and joins all virtual threads upon an unchecked exception before propagating it.</p>
<p style="direction:ltr">Initially, I thought this design choice might provide a strong happens-before guarantee. My assumption was that an application catching a
<code>RuntimeException</code> would be able to <b>observe all side effects</b> from the virtual threads, even though this practice is generally discouraged. This seemed like a potentially significant advantage, outweighing the risk of a virtual thread failing
 to respond to interruption or responding slowly.</p>
<p style="direction:ltr">However, I've since realized that <code>mapConcurrent()</code> cannot fully guarantee a strong happens-before relationship when an unchecked exception occurs
<i>somewhere</i> in the stream pipeline. While it can block and wait for exceptions thrown by the mapper function or downstream operations, it appears unable to intercept unchecked exceptions
<b>thrown by an upstream</b> source.</p>
<p style="direction:ltr">Consider a scenario with two input elements: if the first element starts a virtual thread, and then the second element causes an unchecked exception from the upstream
<i>before</i> reaching the <code>gather()</code> call, the virtual thread initiated by the first element would not be interrupted. This makes the "happens-before" guarantee quite nuanced in practice.</p>
<p style="direction:ltr">This brings me to my core questions:</p>
<ol start="1" style="direction:ltr">
<li>
<p role="presentation" style="direction:ltr">Is providing a happens-before guarantee upon an unchecked exception a design goal for
<code>mapConcurrent()</code>?</p>
</li><li>
<p role="presentation" style="direction:ltr">If not, would it be more desirable to
<i>not</i> join on virtual threads when unchecked exceptions occur? This would allow the application code to catch the exception sooner and avoid the risk of being blocked indefinitely.</p>
</li></ol>
<p style="direction:ltr">Thank you for your time and insights.</p>
<p style="direction:ltr">Best regards,</p>
<p style="direction:ltr">Ben Yu</p>
</blockquote>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>

</div></blockquote></div><div><br clear="all"></div><br><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div>