# 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>`

Functional Interface:
  This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface 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 stream of the completed subtasks for `join` to return when all subtasks complete successfully. It cancels the scope and causes `join` to throw if any subtask fails.
- `anySuccessfulResultOrThrow()` 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. 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 stream 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 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.

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

Since:
  25
See Also:
  - `StructuredTaskScope.open(Joiner)`PREVIEW
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 task 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 defined by this interface may be invoked by several threads concurrently.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static <T> StructuredTaskScope.JoinerPREVIEW<T, Stream<StructuredTaskScope.SubtaskPREVIEW<T>>>`
  `allSuccessfulOrThrow()`
  Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete successfully.
  `static <T> StructuredTaskScope.JoinerPREVIEW<T, Stream<StructuredTaskScope.SubtaskPREVIEW<T>>>`
  `allUntil(Predicate<StructuredTaskScope.SubtaskPREVIEW<? extends T>> isDone)`
  Returns a new Joiner object that yields a stream of all subtasks when all subtasks complete or a predicate returns `true` to cancel the scope.
  `static <T> StructuredTaskScope.JoinerPREVIEW<T,T>`
  `anySuccessfulResultOrThrow()`
  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<? extends 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<? extends T> subtask)`
  Invoked by `fork(Callable)`PREVIEW and `fork(Runnable)`PREVIEW when forking a subtask.
  `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<? extends T> subtask)
    Invoked by `fork(Callable)`PREVIEW and `fork(Runnable)`PREVIEW when forking a subtask. The method is invoked from the task owner thread. The method is invoked before a thread is created to run the subtask.
    Parameters:
      `subtask` - the subtask
    Returns:
      `true` to cancel the scope, otherwise `false`
    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`.

  - ### onComplete

    default boolean onComplete(StructuredTaskScope.SubtaskPREVIEW<? extends 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.
    Parameters:
      `subtask` - the subtask
    Returns:
      `true` to cancel the scope, otherwise `false`
    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`.

  - ### 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, and invoked more than once, is undefined. Where possible, an implementation should return an equal result (or throw the same exception) on second or subsequent calls to produce the outcome.

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

  - ### allSuccessfulOrThrow

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

    If all subtasks complete successfully, the joiner's `result()` method returns a stream of all subtasks in the order that they were forked. If any subtask failed then the `result` method throws the exception from the first subtask to fail.

    Type Parameters:
      `T` - the result type of subtasks
    Returns:
      a new Joiner object that yields a stream of all subtasks when all subtasks complete successfully
    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.

  - ### anySuccessfulResultOrThrow

    static <T> StructuredTaskScope.JoinerPREVIEW<T,T> anySuccessfulResultOrThrow()
    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. 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.

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

  - ### 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.

    Type Parameters:
      `T` - the result type of subtasks
    Returns:
      a new Joiner object that waits for subtasks to complete successfully
    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.

  - ### 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`.

    Type Parameters:
      `T` - the result type of subtasks
    Returns:
      a new Joiner object that waits for all subtasks to complete
    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));
                    }
                }
            }

  - ### allUntil

    static <T> StructuredTaskScope.JoinerPREVIEW<T, Stream<StructuredTaskScope.SubtaskPREVIEW<T>>> allUntil(Predicate<StructuredTaskScope.SubtaskPREVIEW<? extends T>> isDone)
    Returns a new Joiner object that yields a stream 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 stream of all subtasks, in fork order. The stream 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 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<? extends T>> {
                private final AtomicInteger failedCount = new AtomicInteger();
                @Override
                public boolean test(Subtask<? extends T> subtask) {
                    return subtask.state() == Subtask.State.FAILED
                            && failedCount.incrementAndGet() >= 2;
                }
            }

            var joiner = Joiner.all(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 stream 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().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 stream of all subtasks when all subtasks complete or a predicate returns `true` to cancel the scope