<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Have you tried it out? Trying this stuff out is the best way to see how it works, in any case, observe the following example </div><div dir="ltr"><div style="background-color:rgb(28,31,34);padding:0px 0px 0px 2px"><div style="color:rgb(199,205,209);font-family:Consolas;white-space:pre"><p style="margin:0px"><span style="color:rgb(207,191,173)">   </span><span style="color:rgb(255,0,127)">try</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(82,227,246);background-color:rgb(65,65,4)">ShutdownOnSuccess</span><span style="color:rgb(255,0,127)"><</span><span style="color:rgb(191,164,164)">Integer</span><span style="color:rgb(255,0,127)">></span><span style="color:rgb(207,191,173)"> scope </span><span style="color:rgb(255,0,127)">=</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(255,0,127)">new</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(82,227,246);background-color:rgb(65,65,4)">StructuredTaskScope</span><span style="color:rgb(255,0,127);background-color:rgb(65,65,4)">.</span><span style="color:rgb(167,236,33);background-color:rgb(65,65,4)">ShutdownOnSuccess</span><span style="color:rgb(255,0,127)"><></span><span style="color:rgb(249,250,244)">())</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(249,250,244)">{</span></p><p style="margin:0px"><br></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      </span><span style="color:rgb(197,104,28)">var</span><span style="color:rgb(207,191,173)"> fail </span><span style="color:rgb(255,0,127)">=</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">          scope</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">fork</span><span style="color:rgb(249,250,244)">(</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">              </span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(255,0,127)">-></span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(249,250,244)">{</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">                </span><span style="color:rgb(255,0,127)">throw</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(255,0,127)">new</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(167,236,33)">IllegalAccessException</span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">              </span><span style="color:rgb(249,250,244)">})</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><br></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      scope</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">fork</span><span style="color:rgb(249,250,244)">(</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">          </span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(255,0,127)">-></span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(249,250,244)">{</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">            </span><span style="color:rgb(82,227,246)">Thread</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">sleep</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(82,227,246)">Duration</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">of</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(207,191,173)">random</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">nextInt</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(196,140,255)">0</span><span style="color:rgb(255,0,127)">,</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(196,140,255)">1000</span><span style="color:rgb(249,250,244)">)</span><span style="color:rgb(255,0,127)">,</span><span style="color:rgb(207,191,173)"> ChronoUnit</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(207,191,173)">MILLIS</span><span style="color:rgb(249,250,244)">))</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">            </span><span style="color:rgb(255,0,127)">return</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(196,140,255)">1</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">          </span><span style="color:rgb(249,250,244)">})</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><br></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      scope</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">fork</span><span style="color:rgb(249,250,244)">(</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">          </span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(255,0,127)">-></span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(249,250,244)">{</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">            </span><span style="color:rgb(82,227,246)">Thread</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">sleep</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(82,227,246)">Duration</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">of</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(207,191,173)">random</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">nextInt</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(196,140,255)">0</span><span style="color:rgb(255,0,127)">,</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(196,140,255)">1000</span><span style="color:rgb(249,250,244)">)</span><span style="color:rgb(255,0,127)">,</span><span style="color:rgb(207,191,173)"> ChronoUnit</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(207,191,173)">MILLIS</span><span style="color:rgb(249,250,244)">))</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">            </span><span style="color:rgb(255,0,127)">return</span><span style="color:rgb(207,191,173)"> </span><span style="color:rgb(196,140,255)">2</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">          </span><span style="color:rgb(249,250,244)">})</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><br></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      scope</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">join</span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      </span><span style="color:rgb(255,255,255)">// get first result, (will not care about exceptions as long as one succeeds)</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      scope</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(167,236,33)">result</span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(255,0,127)"><br></span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      </span><span style="color:rgb(255,255,255)">// will throw an exception</span><span style="color:rgb(255,0,127)"><br></span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">      </span><span style="color:rgb(207,191,173)">fail</span><span style="color:rgb(255,0,127)">.</span><span style="color:rgb(190,214,255)">get</span><span style="color:rgb(249,250,244)">()</span><span style="color:rgb(255,0,127)">;</span></p><p style="margin:0px"><span style="color:rgb(207,191,173)">    </span><span style="color:rgb(249,250,244)">}</span></p></div></div></div><div dir="ltr"><br></div><div dir="ltr"><br></div><div dir="ltr">Essentially, you must use the `scope.result()` method to retrieve the result instead of calling the get methods on a particular subtask<input name="virtru-metadata" type="hidden" value="{"email-policy":{"disableCopyPaste":false,"disablePrint":false,"disableForwarding":false,"enableNoauth":false,"expandedWatermarking":false,"expires":false,"sms":false,"expirationNum":1,"expirationUnit":"days","isManaged":false,"persistentProtection":false},"attachments":{},"compose-id":"1","compose-window":{"secure":false}}"></div></div></div></div></div></div><br><div class="gmail_quote" style=""><div dir="ltr" class="gmail_attr">On Fri, Oct 27, 2023 at 12:37 PM Eric Kolotyluk <<a href="mailto:eric@kolotyluk.net">eric@kolotyluk.net</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"><u></u>

  
    
  
  <div>
    <p>Looks good... thanks.</p>
    <p>One slight area of confusion for me was, <br>
    </p>
    <pre><code><T> List<Future<T>> executeAll(List<Callable<T>> tasks)
        throws InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
          List<? extends Supplier<Future<T>>> futures = tasks.stream()
              .map(task -> asFuture(task))
              .map(scope::fork)
              .toList();
          scope.join();
          return futures.stream().map(Supplier::get).toList();
    }
}

static <T> Callable<Future<T>> asFuture(Callable<T> task) {
   return () -> {
       try {
           return CompletableFuture.completedFuture(task.call());
       } catch (Exception ex) {
           return CompletableFuture.failedFuture(ex);
       }
   };
}</code></pre>
    <p></p>
    <p>And what happens if <code>ShutdownOnSuccess</code> is called
      instead. Eventually I reasoned that the right thing should happen,
      but there should only ever be one element in the list. Does the
      scope guarantee only one result?<br>
    </p>
    <ol>
      <li>It would be slightly helpful to point this out in a note so
        that it is more obvious.</li>
      <li>What is less obvious is that with <code>ShutdownOnSuccess</code>
        what happens if one or more of the siblings throw an exception?</li>
      <ul>
        <li>I would hope that so long at least one task succeeds, this
          should not cause the overall success of the scope to fail.</li>
        <li>It would be nice to see this explained more clearly.</li>
        <li> Maybe <code>ShutdownOnSuccess</code> deserves its own
          example, discussing possible edge cases.</li>
      </ul>
    </ol>
    <p>Somehow I am remembering Scala 'for comprehensions' with
      concurrent tasks that 'yield' a result... 😉</p>
    <p>The current situation seems kinda clunky with using one stream to
      collect futures, and yet another stream to collect results. Maybe
      one of the Java architects hates such boilerplate, and will come
      up with an elegant way to reduce/remove such boilerplate.<br>
    </p>
    <p>Sincerely, Eric<br>
    </p>
    <div>On 2023-10-27 7:39 a.m., Mark Reinhold
      wrote:<br>
    </div>
    <blockquote type="cite">
      <pre><a href="https://openjdk.org/jeps/462" target="_blank">https://openjdk.org/jeps/462</a>

  Summary: Simplify concurrent programming by introducing an API for
  structured concurrency. Structured concurrency treats groups of related
  tasks running in different threads as a single unit of work, thereby
  streamlining error handling and cancellation, improving reliability,
  and enhancing observability. This is a preview API.

- Mark</pre>
    </blockquote>
  </div>

</blockquote></div></div>