< prev index next >

src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java

Print this page

 193  *         }
 194  *
 195  *         @Override
 196  *         // @link substring="handleComplete" target="handleComplete" :
 197  *         protected void handleComplete(Future<T> future) {
 198  *             if (future.state() == Future.State.SUCCESS) {
 199  *                 T result = future.resultNow();
 200  *                 results.add(result);
 201  *             }
 202  *         }
 203  *
 204  *         // Returns a stream of results from the subtasks that completed successfully
 205  *         public Stream<T> results() {     // @highlight substring="results"
 206  *             return results.stream();
 207  *         }
 208  *     }
 209  *  }
 210  *
 211  * <h2><a id="TreeStructure">Tree structure</a></h2>
 212  *
 213  * StructuredTaskScopes form a tree where parent-child relations are established
 214  * implicitly when opening a new task scope:
 215  * <ul>
 216  *   <li> A parent-child relation is established when a thread started in a task scope
 217  *   opens its own task scope. A thread started in task scope "A" that opens task scope
 218  *   "B" establishes a parent-child relation where task scope "A" is the parent of task
 219  *   scope "B".
 220  *   <li> A parent-child relation is established with nesting. If a thread opens task
 221  *   scope "B", then opens task scope "C" (before it closes "B"), then the enclosing task
 222  *   scope "B" is the parent of the nested task scope "C".
 223  * </ul>
 224  *
 225  * <p> The tree structure supports confinement checks. The phrase "threads contained in
 226  * the task scope" in method descriptions means threads started in the task scope or
 227  * descendant scopes. {@code StructuredTaskScope} does not define APIs that exposes the
 228  * tree structure at this time.



































 229  *
 230  * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
 231  * or method in this class will cause a {@link NullPointerException} to be thrown.
 232  *
 233  * <h2>Memory consistency effects</h2>
 234  *
 235  * <p> Actions in the owner thread of, or a thread contained in, the task scope prior to
 236  * {@linkplain #fork forking} of a {@code Callable} task
 237  * <a href="../../../../java.base/java/util/concurrent/package-summary.html#MemoryVisibility">
 238  * <i>happen-before</i></a> any actions taken by that task, which in turn <i>happen-before</i>
 239  * the task result is retrieved via its {@code Future}, or <i>happen-before</i> any actions
 240  * taken in a thread after {@linkplain #join() joining} of the task scope.
 241  *
 242  * @jls 17.4.5 Happens-before Order
 243  *
 244  * @param <T> the result type of tasks executed in the scope
 245  * @since 19
 246  */
 247 public class StructuredTaskScope<T> implements AutoCloseable {
 248     private static final VarHandle FUTURES;
 249     static {
 250         try {
 251             MethodHandles.Lookup l = MethodHandles.lookup();
 252             FUTURES = l.findVarHandle(StructuredTaskScope.class, "futures", Set.class);
 253         } catch (Exception e) {
 254             throw new InternalError(e);
 255         }
 256     }
 257 

 263     private volatile Set<Future<?>> futures;
 264 
 265     // set by owner when it forks, reset by owner when it joins
 266     private boolean needJoin;
 267 
 268     // states: OPEN -> SHUTDOWN -> CLOSED
 269     private static final int OPEN     = 0;   // initial state
 270     private static final int SHUTDOWN = 1;
 271     private static final int CLOSED   = 2;
 272 
 273     // scope state, set by owner, read by any thread
 274     private volatile int state;
 275 
 276     /**
 277      * Creates a structured task scope with the given name and thread factory. The task
 278      * scope is optionally named for the purposes of monitoring and management. The thread
 279      * factory is used to {@link ThreadFactory#newThread(Runnable) create} threads when
 280      * tasks are {@linkplain #fork(Callable) forked}. The task scope is owned by the
 281      * current thread.
 282      *






 283      * @param name the name of the task scope, can be null
 284      * @param factory the thread factory
 285      */
 286     public StructuredTaskScope(String name, ThreadFactory factory) {
 287         this.factory = Objects.requireNonNull(factory, "'factory' is null");
 288         this.flock = ThreadFlock.open(name);
 289     }
 290 
 291     /**
 292      * Creates an unnamed structured task scope that creates virtual threads. The task
 293      * scope is owned by the current thread.
 294      *
 295      * <p> This constructor is equivalent to invoking the 2-arg constructor with a name
 296      * of {@code null} and a thread factory that creates virtual threads.
 297      *
 298      * @throws UnsupportedOperationException if preview features are not enabled
 299      */
 300     public StructuredTaskScope() {
 301         PreviewFeatures.ensureEnabled();
 302         this.factory = Thread.ofVirtual().factory();

 350     private void untrack(Future<?> future) {
 351         assert futures != null;
 352         futures.remove(future);
 353     }
 354 
 355     /**
 356      * Invoked when a task completes before the scope is shut down.
 357      *
 358      * <p> The {@code handleComplete} method should be thread safe. It may be invoked by
 359      * several threads concurrently.
 360      *
 361      * @implSpec The default implementation does nothing.
 362      *
 363      * @param future the completed task
 364      */
 365     protected void handleComplete(Future<T> future) { }
 366 
 367     /**
 368      * Starts a new thread to run the given task.
 369      *
 370      * <p> The new thread is created with the task scope's {@link ThreadFactory}.


 371      *
 372      * <p> If the task completes before the task scope is {@link #shutdown() shutdown}
 373      * then the {@link #handleComplete(Future) handle} method is invoked to consume the
 374      * completed task. The {@code handleComplete} method is run when the task completes
 375      * with a result or exception. If the {@code Future} {@link Future#cancel(boolean)
 376      * cancel} method is used the cancel a task before the task scope is shut down, then
 377      * the {@code handleComplete} method is run by the thread that invokes {@code cancel}.
 378      * If the task scope shuts down at or around the same time that the task completes or
 379      * is cancelled then the {@code handleComplete} method may or may not be invoked.

 380      *
 381      * <p> If this task scope is {@linkplain #shutdown() shutdown} (or in the process
 382      * of shutting down) then {@code fork} returns a {@code Future} representing a {@link
 383      * Future.State#CANCELLED cancelled} task that was not run.
 384      *
 385      * <p> This method may only be invoked by the task scope owner or threads contained
 386      * in the task scope. The {@link Future#cancel(boolean) cancel} method of the returned
 387      * {@code Future} object is also restricted to the task scope owner or threads contained
 388      * in the task scope. The {@code cancel} method throws {@link WrongThreadException}
 389      * if invoked from another thread. All other methods on the returned {@code Future}
 390      * object, such as {@link Future#get() get}, are not restricted.
 391      *
 392      * @param task the task to run
 393      * @param <U> the result type
 394      * @return a future
 395      * @throws IllegalStateException if this task scope is closed
 396      * @throws WrongThreadException if the current thread is not the owner or a thread
 397      * contained in the task scope


 398      * @throws RejectedExecutionException if the thread factory rejected creating a
 399      * thread to run the task
 400      */
 401     public <U extends T> Future<U> fork(Callable<? extends U> task) {
 402         Objects.requireNonNull(task, "'task' is null");
 403 
 404         // create future
 405         var future = new FutureImpl<U>(this, task);
 406 
 407         boolean shutdown = (state >= SHUTDOWN);
 408 
 409         if (!shutdown) {
 410             // create thread
 411             Thread thread = factory.newThread(future);
 412             if (thread == null) {
 413                 throw new RejectedExecutionException("Rejected by thread factory");
 414             }
 415 
 416             // attempt to start the thread
 417             try {

 611         if (implShutdown())
 612             flock.wakeup();
 613     }
 614 
 615     /**
 616      * Closes this task scope.
 617      *
 618      * <p> This method first shuts down the task scope (as if by invoking the {@link
 619      * #shutdown() shutdown} method). It then waits for the threads executing any
 620      * unfinished tasks to finish. If interrupted then this method will continue to
 621      * wait for the threads to finish before completing with the interrupt status set.
 622      *
 623      * <p> This method may only be invoked by the task scope owner. If the task scope
 624      * is already closed then the owner invoking this method has no effect.
 625      *
 626      * <p> A {@code StructuredTaskScope} is intended to be used in a <em>structured
 627      * manner</em>. If this method is called to close a task scope before nested task
 628      * scopes are closed then it closes the underlying construct of each nested task scope
 629      * (in the reverse order that they were created in), closes this task scope, and then
 630      * throws {@link StructureViolationException}.






 631      * If a thread terminates without first closing task scopes that it owns then
 632      * termination will cause the underlying construct of each of its open tasks scopes to
 633      * be closed. Closing is performed in the reverse order that the task scopes were
 634      * created in. Thread termination may therefore be delayed when the owner has to wait
 635      * for threads forked in these task scopes to finish.
 636      *
 637      * @throws IllegalStateException thrown after closing the task scope if the owner
 638      * did not invoke join after forking
 639      * @throws WrongThreadException if the current thread is not the owner
 640      * @throws StructureViolationException if a structure violation was detected
 641      */
 642     @Override
 643     public void close() {
 644         ensureOwner();
 645         if (state == CLOSED)
 646             return;
 647 
 648         try {
 649             implShutdown();
 650             flock.close();

 807      */
 808     public static final class ShutdownOnSuccess<T> extends StructuredTaskScope<T> {
 809         private static final VarHandle FUTURE;
 810         static {
 811             try {
 812                 MethodHandles.Lookup l = MethodHandles.lookup();
 813                 FUTURE = l.findVarHandle(ShutdownOnSuccess.class, "future", Future.class);
 814             } catch (Exception e) {
 815                 throw new InternalError(e);
 816             }
 817         }
 818         private volatile Future<T> future;
 819 
 820         /**
 821          * Constructs a new {@code ShutdownOnSuccess} with the given name and thread factory.
 822          * The task scope is optionally named for the purposes of monitoring and management.
 823          * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
 824          * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope is
 825          * owned by the current thread.
 826          *






 827          * @param name the name of the task scope, can be null
 828          * @param factory the thread factory
 829          */
 830         public ShutdownOnSuccess(String name, ThreadFactory factory) {
 831             super(name, factory);
 832         }
 833 
 834         /**
 835          * Constructs a new unnamed {@code ShutdownOnSuccess} that creates virtual threads.
 836          *
 837          * <p> This constructor is equivalent to invoking the 2-arg constructor with a
 838          * name of {@code null} and a thread factory that creates virtual threads.
 839          */
 840         public ShutdownOnSuccess() {
 841             super(null, Thread.ofVirtual().factory());
 842         }
 843 
 844         /**
 845          * Shut down the given task scope when invoked for the first time with a {@code
 846          * Future} for a task that completed with a result.

 983      */
 984     public static final class ShutdownOnFailure extends StructuredTaskScope<Object> {
 985         private static final VarHandle FUTURE;
 986         static {
 987             try {
 988                 MethodHandles.Lookup l = MethodHandles.lookup();
 989                 FUTURE = l.findVarHandle(ShutdownOnFailure.class, "future", Future.class);
 990             } catch (Exception e) {
 991                 throw new InternalError(e);
 992             }
 993         }
 994         private volatile Future<Object> future;
 995 
 996         /**
 997          * Constructs a new {@code ShutdownOnFailure} with the given name and thread factory.
 998          * The task scope is optionally named for the purposes of monitoring and management.
 999          * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
1000          * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope
1001          * is owned by the current thread.
1002          *






1003          * @param name the name of the task scope, can be null
1004          * @param factory the thread factory
1005          */
1006         public ShutdownOnFailure(String name, ThreadFactory factory) {
1007             super(name, factory);
1008         }
1009 
1010         /**
1011          * Constructs a new unnamed {@code ShutdownOnFailure} that creates virtual threads.
1012          *
1013          * <p> This constructor is equivalent to invoking the 2-arg constructor with a
1014          * name of {@code null} and a thread factory that creates virtual threads.
1015          */
1016         public ShutdownOnFailure() {
1017             super(null, Thread.ofVirtual().factory());
1018         }
1019 
1020         /**
1021          * Shut down the given task scope when invoked for the first time with a {@code
1022          * Future} for a task that completed abnormally (exception or cancelled).

 193  *         }
 194  *
 195  *         @Override
 196  *         // @link substring="handleComplete" target="handleComplete" :
 197  *         protected void handleComplete(Future<T> future) {
 198  *             if (future.state() == Future.State.SUCCESS) {
 199  *                 T result = future.resultNow();
 200  *                 results.add(result);
 201  *             }
 202  *         }
 203  *
 204  *         // Returns a stream of results from the subtasks that completed successfully
 205  *         public Stream<T> results() {     // @highlight substring="results"
 206  *             return results.stream();
 207  *         }
 208  *     }
 209  *  }
 210  *
 211  * <h2><a id="TreeStructure">Tree structure</a></h2>
 212  *
 213  * Task scopes form a tree where parent-child relations are established implicitly when
 214  * opening a new task scope:
 215  * <ul>
 216  *   <li> A parent-child relation is established when a thread started in a task scope
 217  *   opens its own task scope. A thread started in task scope "A" that opens task scope
 218  *   "B" establishes a parent-child relation where task scope "A" is the parent of task
 219  *   scope "B".
 220  *   <li> A parent-child relation is established with nesting. If a thread opens task
 221  *   scope "B", then opens task scope "C" (before it closes "B"), then the enclosing task
 222  *   scope "B" is the parent of the nested task scope "C".
 223  * </ul>
 224  *
 225  * The <i>descendants</i> of a task scope are the child task scopes that it is a parent
 226  * of, plus the descendants of the child task scopes, recursively.
 227  *
 228  * <p> The tree structure supports:
 229  * <ul>
 230  *   <li> Inheritance of {@linkplain ScopedValue scoped values} across threads.
 231  *   <li> Confinement checks. The phrase "threads contained in the task scope" in method
 232  *   descriptions means threads started in the task scope or descendant scopes.
 233  * </ul>
 234  *
 235  * <p> The following example demonstrates the inheritance of a scoped value. A scoped
 236  * value {@code USERNAME} is bound to the value "{@code duke}". A {@code StructuredTaskScope}
 237  * is created and its {@code fork} method invoked to start a thread to execute {@code
 238  * childTask}. The thread inherits the scoped value <em>bindings</em> captured when
 239  * creating the task scope. The code in {@code childTask} uses the value of the scoped
 240  * value and so reads the value "{@code duke}".
 241  * {@snippet lang=java :
 242  *     private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();
 243  *
 244  *     // @link substring="where" target="ScopedValue#where(ScopedValue, Object, Runnable)" :
 245  *     ScopedValue.where(USERNAME, "duke", () -> {
 246  *         try (var scope = new StructuredTaskScope<String>()) {
 247  *
 248  *             scope.fork(() -> childTask());           // @highlight substring="fork"
 249  *             ...
 250  *          }
 251  *     });
 252  *
 253  *     ...
 254  *
 255  *     String childTask() {
 256  *         // @link substring="get" target="ScopedValue#get()" :
 257  *         String name = USERNAME.get();   // "duke"
 258  *         ...
 259  *     }
 260  * }
 261  *
 262  * <p> {@code StructuredTaskScope} does not define APIs that exposes the tree structure
 263  * at this time.
 264  *
 265  * <p> Unless otherwise specified, passing a {@code null} argument to a constructor
 266  * or method in this class will cause a {@link NullPointerException} to be thrown.
 267  *
 268  * <h2>Memory consistency effects</h2>
 269  *
 270  * <p> Actions in the owner thread of, or a thread contained in, the task scope prior to
 271  * {@linkplain #fork forking} of a {@code Callable} task
 272  * <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility">
 273  * <i>happen-before</i></a> any actions taken by that task, which in turn <i>happen-before</i>
 274  * the task result is retrieved via its {@code Future}, or <i>happen-before</i> any actions
 275  * taken in a thread after {@linkplain #join() joining} of the task scope.
 276  *
 277  * @jls 17.4.5 Happens-before Order
 278  *
 279  * @param <T> the result type of tasks executed in the scope
 280  * @since 19
 281  */
 282 public class StructuredTaskScope<T> implements AutoCloseable {
 283     private static final VarHandle FUTURES;
 284     static {
 285         try {
 286             MethodHandles.Lookup l = MethodHandles.lookup();
 287             FUTURES = l.findVarHandle(StructuredTaskScope.class, "futures", Set.class);
 288         } catch (Exception e) {
 289             throw new InternalError(e);
 290         }
 291     }
 292 

 298     private volatile Set<Future<?>> futures;
 299 
 300     // set by owner when it forks, reset by owner when it joins
 301     private boolean needJoin;
 302 
 303     // states: OPEN -> SHUTDOWN -> CLOSED
 304     private static final int OPEN     = 0;   // initial state
 305     private static final int SHUTDOWN = 1;
 306     private static final int CLOSED   = 2;
 307 
 308     // scope state, set by owner, read by any thread
 309     private volatile int state;
 310 
 311     /**
 312      * Creates a structured task scope with the given name and thread factory. The task
 313      * scope is optionally named for the purposes of monitoring and management. The thread
 314      * factory is used to {@link ThreadFactory#newThread(Runnable) create} threads when
 315      * tasks are {@linkplain #fork(Callable) forked}. The task scope is owned by the
 316      * current thread.
 317      *
 318      * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
 319      * bindings for inheritance by threads created in the task scope. The
 320      * <a href="#TreeStructure">Tree Structure</a> section in the class description
 321      * details how parent-child relations are established implicitly for the purpose of
 322      * inheritance of scoped value bindings.
 323      *
 324      * @param name the name of the task scope, can be null
 325      * @param factory the thread factory
 326      */
 327     public StructuredTaskScope(String name, ThreadFactory factory) {
 328         this.factory = Objects.requireNonNull(factory, "'factory' is null");
 329         this.flock = ThreadFlock.open(name);
 330     }
 331 
 332     /**
 333      * Creates an unnamed structured task scope that creates virtual threads. The task
 334      * scope is owned by the current thread.
 335      *
 336      * <p> This constructor is equivalent to invoking the 2-arg constructor with a name
 337      * of {@code null} and a thread factory that creates virtual threads.
 338      *
 339      * @throws UnsupportedOperationException if preview features are not enabled
 340      */
 341     public StructuredTaskScope() {
 342         PreviewFeatures.ensureEnabled();
 343         this.factory = Thread.ofVirtual().factory();

 391     private void untrack(Future<?> future) {
 392         assert futures != null;
 393         futures.remove(future);
 394     }
 395 
 396     /**
 397      * Invoked when a task completes before the scope is shut down.
 398      *
 399      * <p> The {@code handleComplete} method should be thread safe. It may be invoked by
 400      * several threads concurrently.
 401      *
 402      * @implSpec The default implementation does nothing.
 403      *
 404      * @param future the completed task
 405      */
 406     protected void handleComplete(Future<T> future) { }
 407 
 408     /**
 409      * Starts a new thread to run the given task.
 410      *
 411      * <p> The new thread is created with the task scope's {@link ThreadFactory}. It
 412      * inherits the current thread's {@linkplain ScopedValue scoped value} bindings. The
 413      * bindings must match the bindings captured when the task scope was created.
 414      *
 415      * <p> If the task completes before the task scope is {@link #shutdown() shutdown}
 416      * then the {@link #handleComplete(Future) handleComplete} method is invoked to
 417      * consume the completed task. The {@code handleComplete} method is run when the task
 418      * completes with a result or exception. If the {@code Future}'s {@link
 419      * Future#cancel(boolean) cancel} method is used to cancel a task before the task scope
 420      * is shut down, then the {@code handleComplete} method is run by the thread that
 421      * invokes {@code cancel}. If the task scope shuts down at or around the same time
 422      * that the task completes or is cancelled then the {@code handleComplete} method may
 423      * or may not be invoked.
 424      *
 425      * <p> If this task scope is {@linkplain #shutdown() shutdown} (or in the process
 426      * of shutting down) then {@code fork} returns a {@code Future} representing a {@link
 427      * Future.State#CANCELLED cancelled} task that was not run.
 428      *
 429      * <p> This method may only be invoked by the task scope owner or threads contained
 430      * in the task scope. The {@link Future#cancel(boolean) cancel} method of the returned
 431      * {@code Future} object is also restricted to the task scope owner or threads contained
 432      * in the task scope. The {@code cancel} method throws {@link WrongThreadException}
 433      * if invoked from another thread. All other methods on the returned {@code Future}
 434      * object, such as {@link Future#get() get}, are not restricted.
 435      *
 436      * @param task the task to run
 437      * @param <U> the result type
 438      * @return a future
 439      * @throws IllegalStateException if this task scope is closed
 440      * @throws WrongThreadException if the current thread is not the owner or a thread
 441      * contained in the task scope
 442      * @throws StructureViolationException if the current scoped value bindings are not
 443      * the same as when the task scope was created
 444      * @throws RejectedExecutionException if the thread factory rejected creating a
 445      * thread to run the task
 446      */
 447     public <U extends T> Future<U> fork(Callable<? extends U> task) {
 448         Objects.requireNonNull(task, "'task' is null");
 449 
 450         // create future
 451         var future = new FutureImpl<U>(this, task);
 452 
 453         boolean shutdown = (state >= SHUTDOWN);
 454 
 455         if (!shutdown) {
 456             // create thread
 457             Thread thread = factory.newThread(future);
 458             if (thread == null) {
 459                 throw new RejectedExecutionException("Rejected by thread factory");
 460             }
 461 
 462             // attempt to start the thread
 463             try {

 657         if (implShutdown())
 658             flock.wakeup();
 659     }
 660 
 661     /**
 662      * Closes this task scope.
 663      *
 664      * <p> This method first shuts down the task scope (as if by invoking the {@link
 665      * #shutdown() shutdown} method). It then waits for the threads executing any
 666      * unfinished tasks to finish. If interrupted then this method will continue to
 667      * wait for the threads to finish before completing with the interrupt status set.
 668      *
 669      * <p> This method may only be invoked by the task scope owner. If the task scope
 670      * is already closed then the owner invoking this method has no effect.
 671      *
 672      * <p> A {@code StructuredTaskScope} is intended to be used in a <em>structured
 673      * manner</em>. If this method is called to close a task scope before nested task
 674      * scopes are closed then it closes the underlying construct of each nested task scope
 675      * (in the reverse order that they were created in), closes this task scope, and then
 676      * throws {@link StructureViolationException}.
 677      *
 678      * Similarly, if this method is called to close a task scope while executing with
 679      * {@linkplain ScopedValue scoped value} bindings, and the task scope was created
 680      * before the scoped values were bound, then {@code StructureViolationException} is
 681      * thrown after closing the task scope.
 682      *
 683      * If a thread terminates without first closing task scopes that it owns then
 684      * termination will cause the underlying construct of each of its open tasks scopes to
 685      * be closed. Closing is performed in the reverse order that the task scopes were
 686      * created in. Thread termination may therefore be delayed when the owner has to wait
 687      * for threads forked in these task scopes to finish.
 688      *
 689      * @throws IllegalStateException thrown after closing the task scope if the owner
 690      * did not invoke join after forking
 691      * @throws WrongThreadException if the current thread is not the owner
 692      * @throws StructureViolationException if a structure violation was detected
 693      */
 694     @Override
 695     public void close() {
 696         ensureOwner();
 697         if (state == CLOSED)
 698             return;
 699 
 700         try {
 701             implShutdown();
 702             flock.close();

 859      */
 860     public static final class ShutdownOnSuccess<T> extends StructuredTaskScope<T> {
 861         private static final VarHandle FUTURE;
 862         static {
 863             try {
 864                 MethodHandles.Lookup l = MethodHandles.lookup();
 865                 FUTURE = l.findVarHandle(ShutdownOnSuccess.class, "future", Future.class);
 866             } catch (Exception e) {
 867                 throw new InternalError(e);
 868             }
 869         }
 870         private volatile Future<T> future;
 871 
 872         /**
 873          * Constructs a new {@code ShutdownOnSuccess} with the given name and thread factory.
 874          * The task scope is optionally named for the purposes of monitoring and management.
 875          * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
 876          * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope is
 877          * owned by the current thread.
 878          *
 879          * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
 880          * bindings for inheritance by threads created in the task scope. The
 881          * <a href="StructuredTaskScope.html#TreeStructure">Tree Structure</a> section in
 882          * the class description details how parent-child relations are established
 883          * implicitly for the purpose of inheritance of scoped value bindings.
 884          *
 885          * @param name the name of the task scope, can be null
 886          * @param factory the thread factory
 887          */
 888         public ShutdownOnSuccess(String name, ThreadFactory factory) {
 889             super(name, factory);
 890         }
 891 
 892         /**
 893          * Constructs a new unnamed {@code ShutdownOnSuccess} that creates virtual threads.
 894          *
 895          * <p> This constructor is equivalent to invoking the 2-arg constructor with a
 896          * name of {@code null} and a thread factory that creates virtual threads.
 897          */
 898         public ShutdownOnSuccess() {
 899             super(null, Thread.ofVirtual().factory());
 900         }
 901 
 902         /**
 903          * Shut down the given task scope when invoked for the first time with a {@code
 904          * Future} for a task that completed with a result.

1041      */
1042     public static final class ShutdownOnFailure extends StructuredTaskScope<Object> {
1043         private static final VarHandle FUTURE;
1044         static {
1045             try {
1046                 MethodHandles.Lookup l = MethodHandles.lookup();
1047                 FUTURE = l.findVarHandle(ShutdownOnFailure.class, "future", Future.class);
1048             } catch (Exception e) {
1049                 throw new InternalError(e);
1050             }
1051         }
1052         private volatile Future<Object> future;
1053 
1054         /**
1055          * Constructs a new {@code ShutdownOnFailure} with the given name and thread factory.
1056          * The task scope is optionally named for the purposes of monitoring and management.
1057          * The thread factory is used to {@link ThreadFactory#newThread(Runnable) create}
1058          * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope
1059          * is owned by the current thread.
1060          *
1061          * <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
1062          * bindings for inheritance by threads created in the task scope. The
1063          * <a href="StructuredTaskScope.html#TreeStructure">Tree Structure</a> section in
1064          * the class description details how parent-child relations are established
1065          * implicitly for the purpose of inheritance of scoped value bindings.
1066          *
1067          * @param name the name of the task scope, can be null
1068          * @param factory the thread factory
1069          */
1070         public ShutdownOnFailure(String name, ThreadFactory factory) {
1071             super(name, factory);
1072         }
1073 
1074         /**
1075          * Constructs a new unnamed {@code ShutdownOnFailure} that creates virtual threads.
1076          *
1077          * <p> This constructor is equivalent to invoking the 2-arg constructor with a
1078          * name of {@code null} and a thread factory that creates virtual threads.
1079          */
1080         public ShutdownOnFailure() {
1081             super(null, Thread.ofVirtual().factory());
1082         }
1083 
1084         /**
1085          * Shut down the given task scope when invoked for the first time with a {@code
1086          * Future} for a task that completed abnormally (exception or cancelled).
< prev index next >