# Interface StructuredTaskScope.Joiner<T,R>

Type Parameters:
  `T` - the result type of subtasks executed in the scope
  `R` - the result type of the scope

Enclosing interface:
  `StructuredTaskScopePREVIEW<T,R>`

public static interface StructuredTaskScope.Joiner<T,R>
`Joiner` is a preview API of the Java platform.
Programs can only use `Joiner` when preview features are enabled.
Preview features may be removed in a future release, or upgraded to permanent features of the Java platform.
An object used with a `StructuredTaskScope`PREVIEW to handle subtask completion and produce the result for the scope owner waiting in the `join`PREVIEW method for subtasks to complete.

Joiner defines static methods to create `Joiner` objects for common cases:

- `allSuccessfulOrThrow()` creates a `Joiner` that yields a list of all results for `join` to return when all subtasks complete successfully. It cancels the scope and causes `join` to throw if any subtask fails.
- `anySuccessfulOrThrow()` creates a `Joiner` that yields the result of the first subtask to succeed for `join` to return. It causes `join` to throw if all subtasks fail.
- `awaitAllSuccessfulOrThrow()` creates a `Joiner` that waits for all successful subtasks. It cancels the scope and causes `join` to throw if any subtask fails.
- `awaitAll()` creates a `Joiner` that waits for all subtasks to complete. It does not cancel the scope or cause `join` to throw.

In addition to the methods to create `Joiner` objects for common cases, the `allUntil(Predicate)` method is defined to create a `Joiner` that yields a list of all subtasks. It is created with a `Predicate` that determines if the scope should continue or be cancelled. This `Joiner` can be built upon to create custom policies that cancel the scope based on some condition.

More advanced policies can be developed by implementing the `Joiner` interface. The `onFork(Subtask)` method is invoked when subtasks are forked. The `onComplete(Subtask)` method is invoked when subtasks complete with a result or exception. These methods return a `boolean` to indicate if the scope should be cancelled. These methods can be used to collect subtasks, results, or exceptions, and control when to cancel the scope. The `result()` method must be implemented to produce the result (or exception) for the `join` method.

If a `StructuredTaskScope` is opened with a timeoutPREVIEW, and the timeout expires before or while waiting in `join()`PREVIEW, then the scope is cancelled, and the `Joiners`'s `onTimeout()` method is invoked to notify the `Joiner` and optionally throw `TimeoutException`PREVIEW. If the `onTimeout()` method does not throw then the `join()` method will invoke the `result()` method to produce a result. This result may be based on the outcome of subtasks that completed before the timeout expired.

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

API Note:
  It is very important that a new `Joiner` object is created for each `StructuredTaskScope`. `Joiner` objects should never be shared with different scopes or re-used after a scope is closed.

  Designing a `Joiner` should take into account the code at the use-site where the results from the `join`PREVIEW method are processed. It should be clear what the `Joiner` does vs. the application code at the use-site. In general, the `Joiner` implementation is not the place for "business logic". A `Joiner` should be designed to be as general purpose as possible.

Implementation Requirements:
  Implementations of this interface must be thread-safe. The `onComplete(Subtask)` method may be invoked concurrently, as multiple subtasks can complete at the same time. Additionally, the `onComplete` method may be called concurrently with the scope owner thread invoking the `onFork(Subtask)` or `onTimeout()` methods.
Since:
  25
See Also:
  - `StructuredTaskScope.open(Joiner)`PREVIEW

## Method Summary

Modifier and Type
Method
Description
`static <T> StructuredTaskScope.JoinerPREVIEW<T,List<T>>`
`allSuccessfulOrThrow()`
Returns a new Joiner object that yields a list of all results when all subtasks complete successfully.
`static <T> StructuredTaskScope.JoinerPREVIEW<T, List<StructuredTaskScope.SubtaskPREVIEW<T>>>`
`allUntil(Predicate<StructuredTaskScope.SubtaskPREVIEW<T>> isDone)`
Returns a new Joiner object that yields a list of all subtasks when all subtasks complete or a predicate returns `true` to cancel the scope.
`static <T> StructuredTaskScope.JoinerPREVIEW<T,T>`
`anySuccessfulOrThrow()`
Returns a new Joiner object that yields the result of any subtask that completed successfully.
`static <T> StructuredTaskScope.JoinerPREVIEW<T,Void>`
`awaitAll()`
Returns a new Joiner object that waits for all subtasks to complete.
`static <T> StructuredTaskScope.JoinerPREVIEW<T,Void>`
`awaitAllSuccessfulOrThrow()`
Returns a new Joiner object that waits for subtasks to complete successfully.
`default boolean`
`onComplete(StructuredTaskScope.SubtaskPREVIEW<T> subtask)`
Invoked by the thread started to execute a subtask after the subtask completes successfully or fails with an exception.
`default boolean`
`onFork(StructuredTaskScope.SubtaskPREVIEW<T> subtask)`
Invoked by `fork(Callable)`PREVIEW and `fork(Runnable)`PREVIEW when forking a subtask.
`default void`
`onTimeout()`
Invoked by the `join()`PREVIEW method if the scope was opened with a timeout, and the timeout expires before or while waiting in the `join` method.
`R`
`result()`
Invoked by the `join()`PREVIEW method to produce the result (or exception) after waiting for all subtasks to complete or the scope cancelled.

## Method Details

### onFork

default boolean onFork(StructuredTaskScope.SubtaskPREVIEW<T> subtask)
Invoked by `fork(Callable)`PREVIEW and `fork(Runnable)`PREVIEW when forking a subtask. The method is invoked before a thread is created to run the subtask.

API Note:
  This method is invoked by the `fork` methods. It should not be invoked directly.
Implementation Requirements:
  The default implementation throws `NullPointerException` if the subtask is `null`. It throws `IllegalArgumentException` if the subtask is not in the `UNAVAILABLE`PREVIEW state, it otherwise returns `false`.
Parameters:
  `subtask` - the subtask
Returns:
  `true` to cancel the scope, otherwise `false`

### onComplete

default boolean onComplete(StructuredTaskScope.SubtaskPREVIEW<T> subtask)
Invoked by the thread started to execute a subtask after the subtask completes successfully or fails with an exception. This method is not invoked if a subtask completes after the scope is cancelled.

API Note:
  This method is invoked by subtasks when they complete. It should not be invoked directly.
Implementation Requirements:
  The default implementation throws `NullPointerException` if the subtask is `null`. It throws `IllegalArgumentException` if the subtask is not in the `SUCCESS`PREVIEW or `FAILED`PREVIEW state, it otherwise returns `false`.
Parameters:
  `subtask` - the subtask
Returns:
  `true` to cancel the scope, otherwise `false`

### onTimeout

default void onTimeout()
Invoked by the `join()`PREVIEW method if the scope was opened with a timeout, and the timeout expires before or while waiting in the `join` method.

API Note:
  This method is intended for `Joiner` implementations that do not throw `TimeoutException`PREVIEW, or require a notification when the timeout expires before or while waiting in `join`.

  This method is invoked by the `join` method. It should not be invoked directly.

Implementation Requirements:
  The default implementation throws `TimeoutException`PREVIEW.
Throws:
  `StructuredTaskScope.TimeoutExceptionPREVIEW` - for `join` to throw
Since:
  26

### result

R result() throws Throwable
Invoked by the `join()`PREVIEW method to produce the result (or exception) after waiting for all subtasks to complete or the scope cancelled. The result from this method is returned by the `join` method. If this method throws, then `join` throws `StructuredTaskScope.FailedException`PREVIEW with the exception thrown by this method as the cause.

In normal usage, this method will be called at most once by the `join` method to produce the result (or exception). The behavior of this method when invoked directly is undefined.

API Note:
  This method is invoked by the `join` method. It should not be invoked directly.
Returns:
  the result
Throws:
  `Throwable` - the exception

### allSuccessfulOrThrow

static <T> StructuredTaskScope.JoinerPREVIEW<T,List<T>> allSuccessfulOrThrow()
Returns a new Joiner object that yields a list of all results when all subtasks complete successfully. The `Joiner` cancels the scope and causes `join` to throw if any subtask fails.

If all subtasks complete successfully then the joiner's `result()` method returns a list of all results, in the order that the subtasks were forked, for the `join()`PREVIEW to return. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete, then the `join` method throws `TimeoutException`.

API Note:
  Joiners returned by this method are suited to cases where all subtasks return a result of the same type. Joiners returned by `awaitAllSuccessfulOrThrow()` are suited to cases where the subtasks return results of different types.
Type Parameters:
  `T` - the result type of subtasks
Returns:
  a new Joiner object that yields a list of all results when all subtasks complete successfully

### anySuccessfulOrThrow

static <T> StructuredTaskScope.JoinerPREVIEW<T,T> anySuccessfulOrThrow()
Returns a new Joiner object that yields the result of any subtask that completed successfully. The `Joiner` causes `join` to throw if all subtasks fail.

The joiner's `result()` method returns the result of a subtask, that completed successfully, for the `join()`PREVIEW to return. If all subtasks fail then the `result` method throws the exception from one of the failed subtasks. The `result` method throws `NoSuchElementException` if no subtasks were forked. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for any subtask to complete successfully, then the `join` method throws `TimeoutException`.

Type Parameters:
  `T` - the result type of subtasks
Returns:
  a new Joiner object that yields the result of any subtask that completed successfully
Since:
  26

### awaitAllSuccessfulOrThrow

static <T> StructuredTaskScope.JoinerPREVIEW<T,Void> awaitAllSuccessfulOrThrow()
Returns a new Joiner object that waits for subtasks to complete successfully. The `Joiner` cancels the scope and causes `join` to throw if any subtask fails.

The joiner's `result` method returns `null` if all subtasks complete successfully, or throws the exception from the first subtask to fail. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete, then the `join` method throws `TimeoutException`.

API Note:
  Joiners returned by this method are suited to cases where subtasks return results of different types. Joiners returned by `allSuccessfulOrThrow()` are suited to cases where the subtasks return a result of the same type.
Type Parameters:
  `T` - the result type of subtasks
Returns:
  a new Joiner object that waits for subtasks to complete successfully

### awaitAll

static <T> StructuredTaskScope.JoinerPREVIEW<T,Void> awaitAll()
Returns a new Joiner object that waits for all subtasks to complete. The `Joiner` does not cancel the scope if a subtask fails.

The joiner's `result` method returns `null`. If the scope was opened with a timeoutPREVIEW, and the timeout expires before or while waiting for all subtasks to complete, then the `join` method throws `TimeoutException`.

API Note:
  This Joiner is useful for cases where subtasks make use of side-effects rather than return results or fail with exceptions. The `fork(Runnable)`PREVIEW method can be used to fork subtasks that do not return a result.

  This Joiner can also be used for fan-in scenarios where subtasks are forked to handle incoming connections and the number of subtasks is unbounded. In this example, the thread executing the `acceptLoop` method will only stop when interrupted or the listener socket is closed asynchronously.

        void acceptLoop(ServerSocket listener) throws IOException, InterruptedException {
            try (var scope = StructuredTaskScope.open(Joiner.<Socket>awaitAll())) {
                while (true) {
                    Socket socket = listener.accept();
                    scope.fork(() -> handle(socket));
                }
            }
        }

Type Parameters:
  `T` - the result type of subtasks
Returns:
  a new Joiner object that waits for all subtasks to complete

### allUntil

static <T> StructuredTaskScope.JoinerPREVIEW<T, List<StructuredTaskScope.SubtaskPREVIEW<T>>> allUntil(Predicate<StructuredTaskScope.SubtaskPREVIEW<T>> isDone)
Returns a new Joiner object that yields a list of all subtasks when all subtasks complete or a predicate returns `true` to cancel the scope.

The joiner's `onComplete(Subtask)` method invokes the predicate's `test` method with the subtask that completed successfully or failed with an exception. If the `test` method returns `true` then the scope is cancelled. The `test` method must be thread safe as it may be invoked concurrently from several threads. If the `test` method completes with an exception or error, then the thread that executed the subtask invokes the uncaught exception handler with the exception or error before the thread terminates.

The joiner's `result()` method returns the list of all subtasks, in fork order. The list may contain subtasks that have completed (in `SUCCESS`PREVIEW or `FAILED`PREVIEW state) or subtasks in the `UNAVAILABLE`PREVIEW state if the scope was cancelled before all subtasks were forked or completed.

The joiner's `onTimeout()` method does nothing. If configured with a timeoutPREVIEW, and the timeout expires before or while waiting in `join`PREVIEW, then the `result()` method returns the list of all subtasks. Subtasks that did not complete before the timeout expired will be in the `UNAVAILABLE`PREVIEW state.

The following example uses this method to create a `Joiner` that cancels the scope when two or more subtasks fail.

       class CancelAfterTwoFailures<T> implements Predicate<Subtask<T>> {
            private final AtomicInteger failedCount = new AtomicInteger();
            @Override
            public boolean test(Subtask<T> subtask) {
                return subtask.state() == Subtask.State.FAILED
                        && failedCount.incrementAndGet() >= 2;
            }
        }

        var joiner = Joiner.allUntil(new CancelAfterTwoFailures<String>());

The following example uses `allUntil` to wait for all subtasks to complete without any cancellation. This is similar to `awaitAll()` except that it yields a list of the completed subtasks.

       <T> List<Subtask<T>> invokeAll(Collection<Callable<T>> tasks) throws InterruptedException {
           try (var scope = StructuredTaskScope.open(Joiner.<T>allUntil(_ -> false))) {
               tasks.forEach(scope::fork);
               return scope.join();
           }
       }

The following example uses `allUntil` to get the results of all subtasks that complete successfully within a timeout period.

       <T> List<T> invokeAll(Collection<Callable<T>> tasks, Duration timeout) throws InterruptedException {
       try (var scope = StructuredTaskScope.open(Joiner.<T>allUntil(_ -> false), cf -> cf.withTimeout(timeout))) {
           tasks.forEach(scope::fork);
           return scope.join()
                    .stream()
                    .filter(s -> s.state() == Subtask.State.SUCCESS)
                    .map(Subtask::get)
                    .toList();
            }
        }

Type Parameters:
  `T` - the result type of subtasks
Parameters:
  `isDone` - the predicate to evaluate completed subtasks
Returns:
  a new Joiner object that yields a list of all subtasks when all subtasks complete or a predicate returns `true` to cancel the scope