Module java.base
Package java.util.concurrent

# Class StructuredTaskScope

≠
public class StructuredTaskScope<T>
extends java.lang.Object
implements java.lang.AutoCloseable
Comparing jdk and sv

Type Parameters:
  `T` - the result type of tasks executed in the task scope

All Implemented Interfaces:
  `AutoCloseable`

Direct Known Subclasses:
  `StructuredTaskScope.ShutdownOnFailurePREVIEW` , `StructuredTaskScope.ShutdownOnSuccessPREVIEW`

public class StructuredTaskScope<T> extends Object implements AutoCloseable
`StructuredTaskScope` is a preview API of the Java platform.
Programs can only use `StructuredTaskScope` when preview features are enabled.
Preview features may be removed in a future release, or upgraded to permanent features of the Java platform.
A basic API for structured concurrency . `StructuredTaskScope` supports cases where a task splits into several concurrent subtasks, and where the subtasks must complete before the main task continues. A `StructuredTaskScope` can be used to ensure that the lifetime of a concurrent operation is confined by a syntax block , just like that of a sequential operation in structured programming.

## Basic operation

A `StructuredTaskScope` is created with one of its public constructors. It defines the `fork` method to start a thread to execute a subtask, the `join` method to wait for all subtasks to finish, and the `close` method to close the task scope. The API is intended to be used with the `try-with-resources` statement. The intention is that code in the try block uses the `fork` method to fork threads to execute the subtasks, wait for the subtasks to finish with the `join` method, and then process the results . A call to the `fork` method returns a `Subtask` PREVIEW to representing the forked subtask . Once `join` is called, the `Subtask` can be used to get the result completed successfully, or the exception if the subtask failed.

        Callable<String> task1 = ...
        Callable<Integer> task2 = ...

        try (var scope = new StructuredTaskScope<Object>()) {

            Subtask<String> subtask1 = scope.fork(task1);
            Subtask<Integer> subtask2 = scope.fork(task2);

            scope.join();

            ... process results/exceptions ...

        } // close

The following example forks a collection of homogeneous subtasks, waits for all of them to complete with the `join` method, and uses the `Subtask.State` PREVIEW to partition the subtasks into a set of the subtasks that completed successfully and another for the subtasks that failed.

        List<Callable<String>> callables = ...

        try (var scope = new StructuredTaskScope<String>()) {

            List<Subtask<String>> subtasks = callables.stream().map(scope::fork).toList();

            scope.join();

            Map<Boolean, Set<Subtask<String>>> map = subtasks.stream()
                    .collect(Collectors.partitioningBy(h -> h.state() == Subtask.State.SUCCESS,
                                                       Collectors.toSet()));

        } // close

To ensure correct usage, the `join` and `close` methods may only be invoked by the owner (the thread that opened/created the task scope), and the `close` method throws an exception after closing if the owner did not invoke the `join` method after forking.

`StructuredTaskScope` defines the `shutdown` method to shut down a task scope without closing it. The `shutdown()` method cancels all unfinished subtasks by interrupting the threads. It prevents new threads from starting in the task scope. If the owner is waiting in the `join` method then it will wakeup.

Shutdown is used for short-circuiting and allow subclasses to implement policy that does not require all subtasks to finish.

## Subclasses with policies for common cases

Two subclasses of `StructuredTaskScope` are defined to implement policy for common cases:

1. `ShutdownOnSuccess` PREVIEW captures the result of the first subtask to complete successfully. Once captured, it shuts down the task scope to interrupt unfinished threads and wakeup the owner. This class is intended for cases where the result of any subtask will do ("invoke any") and where there is no need to wait for results of other unfinished subtasks. It defines methods to get the first result or throw an exception if all subtasks fail.
2. `ShutdownOnFailure` PREVIEW captures the exception of the first subtask to fail. Once captured, it shuts down the task scope to interrupt unfinished threads and wakeup the owner. This class is intended for cases where the results of all subtasks are required ("invoke all"); if any subtask fails then the results of other unfinished subtasks are no longer needed. If defines methods to throw an exception if any of the subtasks fail.

The following are two examples that use the two classes. In both cases, a pair of subtasks are forked to fetch resources from two URL locations "left" and "right". The first example creates a ShutdownOnSuccess object to capture the result of the first subtask to complete successfully, cancelling the other by way of shutting down the task scope. The main task waits in `join` until either subtask completes with a result or both subtasks fail. It invokes `result(Function)` PREVIEW method to get the captured result. If both subtasks fail then this method throws a `WebApplicationException` with the exception from one of the subtasks as the cause.

        try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {

            scope.fork(() -> fetch(left));
            scope.fork(() -> fetch(right));

            scope.join();

            String result = scope.result
    (e -> new WebApplicationException(e));

            ...
        }

The second example creates a ShutdownOnFailure object to capture the exception of the first subtask to fail, cancelling the other by way of shutting down the task scope. The main task waits in `joinUntil(Instant)` until both subtasks complete with a result, either fails, or a deadline is reached. It invokes `throwIfFailed(Function)` PREVIEW to throw an exception if either subtask fails. This method is a no-op if both subtasks complete successfully. The example uses `Supplier.get()` to get the result of each subtask. Using `Supplier` instead of `Subtask` is preferred for common cases where the object returned by fork is only used to get the result of a subtask that completed successfully.

       Instant deadline = ...

       try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {

            Supplier<String> supplier1 = scope.fork(() -> query(left));
            Supplier<String> supplier2 = scope.fork(() -> query(right));

            scope.joinUntil(deadline);

            scope.throwIfFailed
    (e -> new WebApplicationException(e));

            // both subtasks completed successfully
            String result = Stream.of(supplier1, supplier2)
                    .map(Supplier::get)
                    .collect(Collectors.joining(", ", "{ ", " }"));

            ...
        }

## Extending StructuredTaskScope

`StructuredTaskScope` can be extended, and the `handleComplete` method overridden, to implement policies other than those implemented by `ShutdownOnSuccess` and `ShutdownOnFailure` . A subclass may, for example, collect the results of subtasks that complete successfully and ignore subtasks that fail. It may collect exceptions when subtasks fail. It may invoke the `shutdown` method to shut down and cause `join` to wakeup when some condition arises.

A subclass will typically define methods to make available results, state, or other outcome to code that executes after the `join` method. A subclass that collects results and ignores subtasks that fail may define a method that returns the results. A subclass that implements a policy to shut down when a subtask fails may define a method to get the exception of the first subtask to fail.

The following is an example of a simple `StructuredTaskScope` implementation that collects homogenous subtasks that complete successfully. It defines the method "`completedSuccessfully()` " that the main task can invoke after it joins.

        class CollectingScope<T> extends StructuredTaskScope<T> {
            private final Queue<Subtask<? extends T>> subtasks = new LinkedTransferQueue<>();

            @Override
            protected void handleComplete(Subtask<? extends T> subtask) {
                if (subtask.state() == Subtask.State.SUCCESS) {
                    subtasks.add(subtask);
                }
            }

            @Override
            public CollectingScope<T> join() throws InterruptedException {
                super.join();
                return this;
            }

            public Stream<Subtask<? extends T>> completedSuccessfully() {
                super.ensureOwnerAndJoined
    ();
                return subtasks.stream();
            }
        }

The implementations of the `completedSuccessfully()` method in the example invokes `ensureOwnerAndJoined()` to ensure that the method can only be invoked by the owner thread and only after it has joined.

## Tree structure

Task scopes form a tree where parent-child relations are established implicitly when opening a new task scope:

- A parent-child relation is established when a thread started in a task scope opens its own task scope. A thread started in task scope "A" that opens task scope "B" establishes a parent-child relation where task scope "A" is the parent of task scope "B".
- A parent-child relation is established with nesting. If a thread opens task scope "B", then opens task scope "C" (before it closes "B"), then the enclosing task scope "B" is the parent of the nested task scope "C".

The descendants of a task scope are the child task scopes that it is a parent of, plus the descendants of the child task scopes, recursively.

The tree structure supports:

- Inheritance of scoped values across threads.
- Confinement checks. The phrase "threads contained in the task scope" in method descriptions means threads started in the task scope or descendant scopes.

The following example demonstrates the inheritance of a scoped value. A scoped value `USERNAME` is bound to the value "`duke` ". A `StructuredTaskScope` is created and its `fork` method invoked to start a thread to execute `childTask` . The thread inherits the scoped value bindings captured when creating the task scope. The code in `childTask` uses the value of the scoped value and so reads the value "`duke` ".

        private static final ScopedValue<String> USERNAME = ScopedValue.newInstance();

        ScopedValue.runWhere
    where(USERNAME, "duke", ).run
    (() -> {
            try (var scope = new StructuredTaskScope<String>()) {

                scope.fork(() -> childTask());
                ...
             }
        });

        ...

        String childTask() {
            String name = USERNAME.get
    ();   // "duke"
            ...
        }

`StructuredTaskScope` does not define APIs that exposes the tree structure at this time.

Unless otherwise specified, passing a `null` argument to a constructor or method in this class will cause a `NullPointerException` to be thrown.

## Memory consistency effects

Actions in the owner thread of, or a thread contained in, the task scope prior to forking of a subtask happen-before any actions taken by that subtask, which in turn happen-before the subtask result is retrievedPREVIEW or happen-before any actions taken in a thread after joining of the task scope.

See Java Language Specification:
  17.4.5 Happens-before Order
Since:
  21

## Nested Types

- = ShutdownOnFailure
- = ShutdownOnSuccess
- = Subtask

## Constructors

- =
  public StructuredTaskScope()
- =
  public StructuredTaskScope(java.lang.String arg0, java.util.concurrent.ThreadFactory arg1)

## Methods

- =
  public void close()
- =
  protected final void ensureOwnerAndJoined()
- =
  public <U> java.util.concurrent.StructuredTaskScope.Subtask<U> fork(java.util.concurrent.Callable<? extends U> arg0)
- =
  protected void handleComplete(java.util.concurrent.StructuredTaskScope.Subtask<? extends T> arg0)
- =
  public final boolean isShutdown()
- =
  public java.util.concurrent.StructuredTaskScope<T> join() throws java.lang.InterruptedException
- =
  public java.util.concurrent.StructuredTaskScope<T> joinUntil(java.time.Instant arg0) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException
- =
  public void shutdown()
- =
  public java.lang.String toString()

## Summary

Differences
| Elements | Comments | Descriptions | Total
Added | Changed | Removed | Added | Changed | Removed | Added | Changed | Removed
--- | --- | --- | --- | --- | --- | --- | --- | ---
StructuredTaskScope |  |  |  |  |  |  | 2 | 1 | 1 | 4
Total |  |  |  |  |  |  | 2 | 1 | 1 | 4