<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 class="elementToProof" 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 opened an issue to track the concern, and I have proposed a change which seems to align well with how parallel streams behave under caller thread interruption.</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I've opened the following PR for review:</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<a href="https://github.com/openjdk/jdk/pull/23467" id="LPlnk">https://github.com/openjdk/jdk/pull/23467</a><br>
<br>
If you are able to make a local OpenJDK build with that solution you could check if it addresses your use-cases (or not).</div>
<div class="_Entity _EType_OWALinkPreview _EId_OWALinkPreview _EReadonly_1" style="color: inherit; background-color: inherit;">
<div id="LPBorder_GTaHR0cHM6Ly9naXRodWIuY29tL29wZW5qZGsvamRrL3B1bGwvMjM0Njc." class="LPBorder930895" style="width: 100%; margin-top: 16px; margin-bottom: 16px; position: relative; max-width: 800px; min-width: 424px;">
<table id="LPContainer930895" role="presentation" style="padding: 12px 36px 12px 12px; width: 100%; border-width: 1px; border-style: solid; border-color: rgb(200, 200, 200); border-radius: 2px;">
<tbody>
<tr valign="top" style="border-spacing: 0px;">
<td>
<div id="LPImageContainer930895" style="position: relative; margin-right: 12px; height: 120px; overflow: hidden; width: 240px;">
<a target="_blank" id="LPImageAnchor930895" href="https://github.com/openjdk/jdk/pull/23467"><img id="LPThumbnailImageId930895" alt="" height="120" style="display: block;" width="240" src="https://opengraph.githubassets.com/00e04f8a63bde12217df087df7ef8edee563adf7e925d07c75bdeae092180094/openjdk/jdk/pull/23467"></a></div>
</td>
<td style="width: 100%;">
<div id="LPTitle930895" style="font-size: 21px; font-weight: 300; margin-right: 8px; font-family: wf_segoe-ui_light, "Segoe UI Light", "Segoe WP Light", "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif; margin-bottom: 12px;">
<a target="_blank" id="LPUrlAnchor930895" href="https://github.com/openjdk/jdk/pull/23467" style="text-decoration: none;">8349462: Gatherers.mapConcurrent could support async interrupts by viktorklang-ora · Pull Request #23467 · openjdk/jdk</a></div>
<div id="LPDescription930895" style="font-size: 14px; max-height: 100px; color: rgb(102, 102, 102); font-family: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif; margin-bottom: 12px; margin-right: 8px; overflow: hidden;">
This change is likely going to need some extra verbiage in the spec for mapConcurrent, and thus a CSR. This behavior aligns mapConcurrent with how parallel streams work in conjunction with interrup...</div>
<div id="LPMetadata930895" style="font-size: 14px; font-weight: 400; color: rgb(166, 166, 166); font-family: wf_segoe-ui_normal, "Segoe UI", "Segoe WP", Tahoma, Arial, sans-serif;">
github.com</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="elementToProof" 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 id="Signature" style="color: inherit;">
<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="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> Jige Yu <yujige@gmail.com><br>
<b>Sent:</b> Wednesday, 5 February 2025 16:24<br>
<b>To:</b> Viktor Klang <viktor.klang@oracle.com><br>
<b>Cc:</b> core-libs-dev@openjdk.org <core-libs-dev@openjdk.org><br>
<b>Subject:</b> Re: [External] : Re: mapConcurrent() with InterruptedException</font>
<div> </div>
</div>
<div>
<div dir="ltr">Thanks Viktor!
<div><br>
</div>
<div>I understand the problem.</div>
<div><br>
</div>
<div>The main reason I asked is because I want to understand how the core Java team thinks of throwing an unchecked exception.</div>
<div><br>
</div>
<div>As explained above, I consider losing cancellability a big deal, a deal breaker even. And I thought throwing unchecked is more acceptable. Because the most common reason the mapConcurrent() VT can be interrupted is due to cancellation from a parent mapConcurrent(),
 or a parent Structured Concurrency scope. The cancellation could be either from an organic exception, or from the downstream not needing more elements, like maybe due to findFirst() already getting an element.</div>
<div><br>
</div>
<div>In both cases, since the concurrent operation is already cancelled (result ignored), what exception pops up to the top level isn't that big of a deal (perhaps only a log record will be seen?)</div>
<div><br>
</div>
<div>But if the core Java team considers it a bad idea, I would love to learn and adjust.</div>
</div>
<br>
<div class="x_gmail_quote x_gmail_quote_container">
<div dir="ltr" class="x_gmail_attr">On Tue, Feb 4, 2025 at 4:41 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com">viktor.klang@oracle.com</a>> wrote:<br>
</div>
<blockquote class="x_gmail_quote" style="margin:0px 0px 0px 0.8ex; border-left:1px solid rgb(204,204,204); padding-left:1ex">
<div class="x_msg5064905880974080681">
<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,</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="line-height:normal; margin:0px; font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
The problem is that mapConcurrent cannot throw InterruptedException because that is a checked exception, so we cannot clear the interrupted flag and throw that exception.</div>
<div style="line-height:normal; margin:0px; font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<div style="line-height:normal; margin:0px; font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
So the updated semantics is to not cut the stream short but instead run to completion, restoring the interruption flag.</div>
<div style="line-height:normal; margin:0px; font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<div style="line-height:normal; margin:0px; font-family:Aptos,Aptos_EmbeddedFont,Aptos_MSFontService,Calibri,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
There exists a couple of alternatives to this approach which I am contemplating, but they need to be further explored before I consider moving forward with any of them.</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 id="x_m_5064905880974080681Signature" style="color:inherit">
<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="x_m_5064905880974080681appendonsend" style="color:inherit"></div>
<hr style="display:inline-block; width:98%">
<div id="x_m_5064905880974080681divRplyFwdMsg" dir="ltr" style="color:inherit"><span style="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> Monday, 27 January 2025 17:00<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: mapConcurrent() with InterruptedException</span>
<div> </div>
</div>
<div style="direction:ltr">Thanks Viktor!</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">It looks like the current fix ignores interruption.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">I want to make sure my concern of it defeating cancellation is heard and understood.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">The scenarios I worry about is for a mapConcurrent() that fans out to another method call, which internally calls mapConcurrent() as implementation detail.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">An example:</div>
<div style="direction:ltr"><br>
</div>
<pre style="margin-top:0px; margin-bottom:0px; border-radius:6px; min-height:52px"><div style="direction:ltr; line-height:1.45; font-size:13.6px; color:rgb(31,35,40)">List<RefundResponse> refundHelper(transaction) {
  transaction.creditCardAccounts.stream()
    .gather(mapConcurrent(acct -> service.refund(acct))
    .toList();
}

transactions.stream()
    .gather(mapConcurrent(transaction -> refundHelper(transaction));</div></pre>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">It seems undesirable that in such a case all the service.refund() calls become non cancellable, because the only way the outer mapConcurrent() cancels the refundHelper() calls is through Thread.interrupt() the virtual threads that
 call refundHelper(), which would then be disabled by the inner mapConcurrent().</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Does this example make sense to you? I can further explain if anything isn't clear.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">But I want to make sure the decision to disable interruption is deliberate judgement call that such nested mapConcurrent() is unlikely,or not important.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Cheers,</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<br>
<div style="direction:ltr">On Mon, Jan 27, 2025 at 6:11 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="x_m_5064905880974080681OWA4b076691-d1e8-8d95-8535-f492ad867ad9" 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!</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)">
Please see: <a href="https://urldefense.com/v3/__https://github.com/openjdk/jdk/pull/23100__;!!ACWV5N9M2RV99hQ!IzQs0G26M7ZGPwJ3YJpCcS0gxi6BjqoBux2T5u0cHud_zb_mHLfiIrASSZiP0ynNgnaAuwuOh__WinK8$" id="x_m_5064905880974080681x_m_7996180640990855094LPlnk656634" target="_blank">
https://github.com/openjdk/jdk/pull/23100</a></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 id="x_m_5064905880974080681x_m_7996180640990855094Signature" style="color:inherit">
<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="x_m_5064905880974080681x_m_7996180640990855094appendonsend" style="color:inherit">
</div>
<hr style="direction:ltr; display:inline-block; width:98%">
<div id="x_m_5064905880974080681x_m_7996180640990855094divRplyFwdMsg" dir="ltr" style="color:inherit">
<span style="font-family:Calibri,sans-serif; font-size:11pt; color:rgb(0,0,0)"><b>From:</b> Jige Yu <<a href="mailto:yujige@gmail.com" id="x_m_5064905880974080681OWAfd8157e5-6f4d-9f10-b298-8879c3ee45b6" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Sunday, 26 January 2025 23:03<br>
<b>To:</b> Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="x_m_5064905880974080681OWAb259d493-c2e0-1be8-57e2-57e67b63de45" target="_blank">viktor.klang@oracle.com</a>><br>
<b>Cc:</b> <a href="mailto:core-libs-dev@openjdk.org" id="x_m_5064905880974080681OWA808cc8c4-3ff9-dc02-483d-bcc1e7e9aed3" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="x_m_5064905880974080681OWAcb2f4969-b604-afac-8fb6-b37f9fe8eb95" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> [External] : Re: mapConcurrent() with InterruptedException</span>
<div> </div>
</div>
<div style="direction:ltr">Checking in on what you've found out, Viktor.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">From where we left off, I understand that you were looking at alternatives instead of silent truncation?</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Have you reached any conclusion?</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">We touched on disallowing interruption during mapConcurrent(). I still have concerns with disabling cancellation, because it basically undoes this API note from the
<a href="https://cr.openjdk.org/~alanb/sc-20240503/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)" id="x_m_5064905880974080681OWA6a69caf3-a2ed-395a-b063-a59c0bd5d640" target="_blank">
javadoc</a>:</div>
<div style="direction:ltr"><br>
</div>
<dl style="color:inherit"><dt style="font-family:"DejaVu Sans",Arial,Helvetica,sans-serif; font-size:0.856em; font-weight:bold; margin:10px 0px 0px; color:rgb(53,56,51)">
API Note:</dt></dl>
<dl style="color:inherit"><dd style="margin:5px 0px 10px 10px; font-size:14px; color:rgb(53,56,51)">
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.</dd></dl>
<div style="direction:ltr">In reality, people will use mapConcurrent() to fan out rpcs. Sometimes these rpcs are just a single blocking call; yet sometimes they may themselves be a Structured Concurrency scope, with 2 or 3 rpcs that constitute a single logical
 operation. Under two conditions, cancellation is imho important semantic:</div>
<ol start="1" style="direction:ltr">
<li style="direction:ltr">The downstream code uses filter().findFirst(), and when it sees an element, it will return and no longer needs the other pending rpcs to complete. If cancellation is disabled, these unnecessary rpcs will waste system resources.</li><li style="direction:ltr">One of the rpc throws and the Stream pipeline needs to propagate the exception. Again, if the other rpcs cannot be cancelled, we'll have many zombie rpcs.</li></ol>
<div style="direction:ltr">Zombie rpcs may or may not be a deal breaker, depending on the specific use case. But for a JDK library, losing cancellation would have a negative impact on usability.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">My 2c,</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">On Fri, Jan 3, 2025 at 9:18 AM Viktor Klang <<a href="mailto:viktor.klang@oracle.com" id="x_m_5064905880974080681OWAaaf1e65b-f589-5987-abde-4ad46c3febdc" 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 Ben,<br>
<br>
Thanks for raising these questions—getting feedback is crucial in the Preview stage of features.<br>
<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)">
I wrote a reply to the Reddit thread so I'll just summarize here:</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)">
It is important to note that <i>mapConcurrent()</i> is not a part of the Structured Concurrency JEPs, so it is not designed to join SC scopes.</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)">
I'm currently experimenting with ignoring-but-restoring interrupts on the "calling thread" for
<i>mapConcurrent()</i>, as well as capping work-in-progress to <i>maxConcurrency</i> (not only capping the concurrency but also the amount of completed-but-yet-to-be-pushed work). Both of these adjustments should increase predictability of behavior in the face
 of blocking operations with variable delays.</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)">
Another adjustment I'm looking at right now is to harden/improve the cleanup to wait for concurrent tasks to acknowledge cancellation, so that once the finisher is done executing the VTs are known to have terminated.</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 not preserving the encounter order, that would be a completely different thing, and I'd encourage you to experiment with that if that functionality would be interesting for your use-case(s).</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)">
Again, thanks for your feedback!</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 id="x_m_5064905880974080681x_m_7996180640990855094x_m_-2136516963982356393Signature" style="color:inherit">
<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="x_m_5064905880974080681x_m_7996180640990855094x_m_-2136516963982356393appendonsend" style="color:inherit">
</div>
<hr style="direction:ltr; display:inline-block; width:98%">
<div id="x_m_5064905880974080681x_m_7996180640990855094x_m_-2136516963982356393divRplyFwdMsg" dir="ltr" style="color:inherit">
<span style="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="x_m_5064905880974080681OWA21623870-5203-54ff-890b-baabafb91b38" target="_blank">core-libs-dev-retn@openjdk.org</a>>
 on behalf of Jige Yu <<a href="mailto:yujige@gmail.com" id="x_m_5064905880974080681OWAc2add8d4-8e32-af71-09cc-6a164865cdad" target="_blank">yujige@gmail.com</a>><br>
<b>Sent:</b> Friday, 3 January 2025 17:53<br>
<b>To:</b> <a href="mailto:core-libs-dev@openjdk.org" id="x_m_5064905880974080681OWA0f757c07-9739-439a-9691-c755869c900d" target="_blank">
core-libs-dev@openjdk.org</a> <<a href="mailto:core-libs-dev@openjdk.org" id="x_m_5064905880974080681OWA9f63b57a-c4d2-99c1-8fa4-67cccb9c08cf" target="_blank">core-libs-dev@openjdk.org</a>><br>
<b>Subject:</b> mapConcurrent() with InterruptedException</span>
<div> </div>
</div>
<div style="direction:ltr">Hi Java Experts,</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">I sent this email incorrectly to loom-dev@ and was told on Reddit that core-libs-dev is the right list.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">The question is about the behavior of mapConcurrent() when the thread is interrupted.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Currently mapConcurrent()'s finisher phase will re-interrupt the thread, then stop at whatever element that has already been processed and return.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">This strikes me as a surprising behavior, because for example if I'm running:</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">   Stream.of(1, 2, 3)</div>
<div style="direction:ltr">        .gather(mapConcurrent(i -> i * 2))</div>
<div style="direction:ltr">        .toList()</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">and the thread is being interrupted, the result could be any of [2], [2, 4] or [2, 4, 6].</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Since thread interruption is cooperative, there is no guarantee that the thread being interrupted will just abort. It's quite possible that it'll keep going and then will use for example [2] as the result of doubling the list of [1,
 2, 3], which is imho incorrect.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">In the <a href="https://urldefense.com/v3/__https://www.reddit.com/r/java/comments/1hr8xyu/observations_of_gatherersmapconcurrent/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button__;!!ACWV5N9M2RV99hQ!L1LHRE2pnYPg43nM0J0dCoV4agscV_rybIV9jY97xn9XJi9d7VoPma4jhx4J4GBeoeQmVud8M4PjPb7L$" id="x_m_5064905880974080681OWAadfc6160-2688-5cf6-9013-a951d48de2ee" target="_blank">
Reddit</a> thread, someone argued that interruption rarely happens so it's more of a theoretical issue. But interruption can easily happen in Structured Concurrency or in mapConcurrent() itself if any subtask has failed in order to cancel/interrupt the other
 ongoing tasks.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">There had been discussion about alternative strategies:</div>
<ol start="1" style="direction:ltr">
<li style="direction:ltr">Don't respond to interruption and just keep running to completion.</li><li style="direction:ltr">Re-interrupt thread and wrap the InterruptedException in a standard unchecked exception (StructuredConcurrencyInterruptedException?).</li></ol>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">I have concerns with option 1 because it disables cancellation propagation when mapConcurrent() itself is used in a subtask of a parent mapConcurrent() or in a StructuredConcurrencyScope.</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Both equivalent Future-composition async code, or C++'s fiber trees support cancellation propagation and imho it's a critical feature or else it's possible that a zombie thread is still sending RPCs long after the main thread has
 exited (failed, or falled back to some default action).</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">My arguments for option 2:</div>
<ol start="1" style="direction:ltr">
<li style="direction:ltr">InterruptedException is more error prone than traditional checked exceptions for
<b>users</b> to catch and handle. They can forget to re-interrupt the thread. It's so confusing that even seasoned programmers may not know they are
<b>supposed to</b> re-interrupt the thread.</li><li style="direction:ltr">With Stream API using functional interfaces like Supplier, Function, the option of just tacking on "throws IE" isn't available to many users.</li><li style="direction:ltr">With Virtual Threads, it will be more acceptable, or even become common to do blocking calls from a stream operation (including but exclusive to mapConcurrent()). So the chance users are forced to deal with IE will become substantially
 higher.</li><li style="direction:ltr">Other APIs such as the Structured Concurrency API have already started wrapping system checked exceptions like ExecutionException, TimeoutException in unchecked exceptions (
<span style="font-family:-apple-system,"system-ui","Segoe UI",Roboto,"Helvetica Neue",Arial,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol",sans-serif; font-size:14px">
<a href="https://urldefense.com/v3/__https://download.java.net/java/early_access/loom/docs/api/java.base/java/util/concurrent/StructuredTaskScope.html*join()__;Iw!!ACWV5N9M2RV99hQ!L1LHRE2pnYPg43nM0J0dCoV4agscV_rybIV9jY97xn9XJi9d7VoPma4jhx4J4GBeoeQmVud8MxGG4HzA$" id="x_m_5064905880974080681OWA59075667-e3c6-c853-6caa-77e7bfe11a32" target="_blank" style="margin-top:0px">join()</a></span> for
 example).</li><li style="direction:ltr">Imho, exceptions that we'd rather users not catch and handle but instead should mostly just propagate up as is, should be unchecked.</li></ol>
<div style="direction:ltr">There is also a <a href="https://urldefense.com/v3/__https://www.reddit.com/r/java/comments/1hr8xyu/comment/m4z4f8c/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button__;!!ACWV5N9M2RV99hQ!L1LHRE2pnYPg43nM0J0dCoV4agscV_rybIV9jY97xn9XJi9d7VoPma4jhx4J4GBeoeQmVud8MyZYl02k$" id="x_m_5064905880974080681OWAef47d881-9ea3-4f13-84bd-82af4c1308d9" target="_blank">
side discussion</a> about whether mapConcurrent() is better off preserving input order or push to downstream as soon as an element is computed. I'd love to discuss that topic too but maybe it's better to start a separate thread?</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Thank you and cheers!</div>
<div style="direction:ltr"><br>
</div>
<div style="direction:ltr">Ben Yu</div>
<div style="direction:ltr"><br>
</div>
</blockquote>
</blockquote>
</div>
</div>
</blockquote>
</div>
</div>
</body>
</html>