Class LLCF

java.lang.Object
io.foldright.cffu.LLCF

public final class LLCF extends Object
Low Level CompletableFuture utility methods for manipulating CompletableFuture. This class is for library writers, the methods intended for end users are in the CompletableFutureUtils class.

In general, you should NEVER use this class, unless you understand the underlying logic of CompletableFuture and need hack it. Because the methods are Low Level, use below the method name convention intentionally:

  • methods with f_ prefix means not type-safe, e.g.
    • return type CompletableFuture that may be a minimal-stage
    • force cast to CompletableFuture<T> from any CompletableFuture<?>
    • return generic type T but constrained runtime type TupleX
  • methods with 0 suffix means no parameter validation, e.g.
    • no null check
Author:
Jerry Lee (oldratlee at gmail dot com)
See Also:
  • Field Details

  • Method Details

    • f_cast

      @Contract(pure=true) public static <T> CompletableFuture<T> f_cast(CompletableFuture<?> cf)
      Force casts CompletableFuture with the value type, IGNORE the compile-time type check.
    • f_toCf0

      @Contract(pure=true) public static <T> CompletableFuture<T> f_toCf0(CompletionStage<? extends T> stage)
      Force converts CompletionStage to CompletableFuture, reuse cf instances as many as possible.

      CAUTION: This method is NOT type safe! Because reused the CF instance, The returned cf may be a minimal-stage, MUST NOT be written or read(explicitly) (e.g. CompletableFuture.complete(T)); Otherwise, the caller usage of cf may throw UnsupportedOperationException.

    • f_toCfArray0

      @Contract(pure=true) public static <T> CompletableFuture<T>[] f_toCfArray0(CompletionStage<? extends T>[] stages)
      Force converts CompletionStage array to CompletableFuture array, reuse cf instances as many as possible. This method is NOT type safe! More info see method f_toCf0(CompletionStage).
    • f_toCfCopy0

      @Contract(pure=true) public static <T> CompletableFuture<T> f_toCfCopy0(CompletionStage<? extends T> stage)
      Converts CompletionStage to a CompletableFuture copy.

      CAUTION: This method is NOT type safe! Because reused the CF instance, The returned cf may be a minimal-stage, MUST NOT be written or read(explicitly) (e.g. CompletableFuture.complete(T)); Otherwise, the caller usage of cf may throw UnsupportedOperationException.

      Implementation Note: The returned instances of calling copy methods (CompletableFuture.copy()) on minimal-stage instances is still minimal-stage (e.g. minimalCompletionStage().copy(), completedStage().copy())

    • f_toCfCopyArray0

      @Contract(pure=true) public static <T> CompletableFuture<T>[] f_toCfCopyArray0(CompletionStage<? extends T>[] stages)
      Converts CompletionStage array to a CompletableFuture copy array. This method is NOT type safe! More info see method f_toCfCopy0(CompletionStage).
    • toNonMinCf0

      @Contract(pure=true) public static <T> CompletableFuture<T> toNonMinCf0(CompletionStage<? extends T> stage)
      Converts CompletionStage to non-minimal-stage CompletableFuture, reuse cf instances as many as possible.

      CAUTION: because reused the CF instance, if the caller need defensive copy instead of writing it directly, use method toNonMinCfCopy0(CompletionStage)).

    • toNonMinCfArray0

      @Contract(pure=true) public static <T> CompletableFuture<T>[] toNonMinCfArray0(CompletionStage<? extends T>[] stages)
      Converts CompletionStage array to non-minimal-stage CompletableFuture array, reuse cf instances as many as possible. More info see method toNonMinCf0(CompletionStage).
    • toNonMinCfCopy0

      @Contract(pure=true) public static <T> CompletableFuture<T> toNonMinCfCopy0(CompletionStage<? extends T> stage)
      Converts CompletionStage to a non-minimal-stage CompletableFuture copy. This method is type safe.

      Implementation Note: The returned instances of calling copy methods (CompletableFuture.copy()) on minimal-stage instances is still minimal-stage (e.g. minimalCompletionStage().copy(), completedStage().copy()).

    • toNonMinCfCopyArray0

      @Contract(pure=true) public static <T> CompletableFuture<T>[] toNonMinCfCopyArray0(CompletionStage<? extends T>[] stages)
      Converts CompletionStage array to a non-minimal-stage CompletableFuture copy array. This method is type safe. More info see method toNonMinCfCopy0(CompletionStage).
    • isMinStageCf

      @Contract(pure=true) public static boolean isMinStageCf(CompletableFuture<?> cf)
      Checks if the given CompletableFuture instance is a minimal-stage.

      Implementation Note: While minimal-stage is implemented as a private subclass of CompletableFuture, the CompletableFuture API consistently uses CompletionStage type for minimal-stage instances and reserves CompletableFuture type for non-minimal-stage instances only.

      This type contract for minimal-stage MUST be followed for end users APIs.

    • peek0

      @Contract("_, _, _ -> param1") public static <T, F extends CompletionStage<? extends T>> F peek0(F cfThis, BiConsumer<? super T,? super Throwable> action, String where)
      Peeks the result by executing the given action when the given stage completes. This method is guaranteed to return the given stage without modifying it; The uncaught exceptions thrown by the action are reported.

      CAUTION: Since this method returns the input stage directly, the execution order between the given action and other actions added to the input stage cannot be guaranteed. The action should be treated as "fire and forget" - do not make any assumptions about timing or execution sequence.

      See Also:
    • peekAsync0

      @Contract("_, _, _, _ -> param1") public static <T, F extends CompletionStage<? extends T>> F peekAsync0(F cfThis, BiConsumer<? super T,? super Throwable> action, String where, Executor executor)
      Peeks the result by executing the given action using the supplied executor when the given stage completes. This method is guaranteed to return the given stage without modifying it; The uncaught exceptions thrown by the action are reported.

      CAUTION: Since this method returns the input stage directly, the execution order between the given action and other actions added to the input stage cannot be guaranteed. The action should be treated as "fire and forget" - do not make any assumptions about timing or execution sequence.

      See Also:
    • completeCf0

      public static <T> boolean completeCf0(CompletableFuture<? super T> cf, @Nullable T value, @Nullable Throwable ex)
      Completes the given CompletableFuture with the exception(if non-null), otherwise with the value. In general, you should NEVER use this method in application codes, use CompletableFuture.complete(Object) or CompletableFuture.completeExceptionally(Throwable) instead.
    • relayAsync0

      public static <T, F extends CompletionStage<?>> F relayAsync0(CompletionStage<? extends T> cfThis, Function<CompletableFuture<T>,F> relayComputations, Executor executor)
      Provides the "relay async" way to arrange execution of a new stage's computations that guarantees the execution of new stage's computations not in the caller thread and minimizes thread switching.

      In CompletionStage (including subclass CompletableFuture), execution of a new stage's computations may be arranged in any of three ways:
      • "default execution",
      • default "asynchronous execution" (using methods with suffix async that employ the stage's default asynchronous execution facility),
      • or custom "asynchronous execution" (via a supplied Executor).
      — the javadoc of CompletionStage
      This relayAsync0 method introduces the fourth way "relay async" to arrange execution of a new stage's computations:
      • If input cf is COMPLETED when computations execute, use "asynchronous execution" way (via supplied Executor); Guarantee that a new stage's computations won't block the sequential codes of caller.
      • Otherwise, use "default execution" way; Save one thread switching.

      CAUTION: Because One more thread switching generally won't lead to performance problems and using "asynchronous execution"(methods with suffix async) is simpler, make wise use of "relay async" way when necessary.

      More info about the "relay async" way (including more description and example codes) see RelayAsyncDescriptionAndExample.java

      Parameters:
      cfThis - the input stage(including CompletableFuture)
      relayComputations - the computations to be arranged after input stage
      executor - the executor used for asynchronous execution
      Returns:
      the return value of function relayComputations
      See Also:
    • safeAddSuppressedEx

      public static void safeAddSuppressedEx(@Nullable Throwable suppressed, Throwable target)
      Adds a suppressed exception to a target exception, first unwrapping the target exception if it is a CompletionException or ExecutionException.

      Unwrapping target exception is necessary to ensures suppressed exceptions are properly preserved, because CompletableFuture internally wraps exceptions in CompletionException / ExecutionException, which can later be unwrapped and discarded during CompletableFuture processing (e.g. CompletableFuture.exceptionNow()), potentially losing any suppressed exceptions that were attached to the wrapper.

      Parameters:
      suppressed - the exception to be added as a suppressed exception. If null, no action is taken
      target - the target exception to add the suppressed exception to
      See Also:
    • nonExSwallowedFunction

      @Contract(value="null, _ -> null; !null, _ -> !null", pure=true) @Nullable public static <X extends Throwable, T, F extends Function<? super X, ? extends T>> F nonExSwallowedFunction(@Nullable F fn, boolean addSuppressedToOriginalEx)
      Wraps a function that processes exceptions to ensure that if error handling throws a new exception, the error context is preserved by calling Throwable.addSuppressed(java.lang.Throwable).
      See Also:
    • nonExSwallowedBiFunction

      @Contract(value="null, _ -> null; !null, _ -> !null", pure=true) @Nullable public static <T, X extends Throwable, U, F extends BiFunction<? super T, ? extends X, ? extends U>> F nonExSwallowedBiFunction(@Nullable F fn, boolean addSuppressedToOriginalEx)
      Wraps a BiFunction that processes exceptions to ensure that if error handling throws a new exception, the error context is preserved by calling Throwable.addSuppressed(java.lang.Throwable).
      See Also:
    • nonExSwallowedBiConsumer

      @Contract(value="null, _ -> null; !null, _ -> !null", pure=true) @Nullable public static <T, X extends Throwable, F extends BiConsumer<? super T, ? super X>> F nonExSwallowedBiConsumer(@Nullable F action, boolean addSuppressedToOriginalEx)
      Wraps a BiConsumer that processes exceptions to ensure that if error handling throws a new exception, the error context is preserved by calling Throwable.addSuppressed(java.lang.Throwable).
      See Also:
    • screenExecutor

      @Contract(pure=true) public static Executor screenExecutor(Executor e)
      Null-checks user executor argument, and translates uses of commonPool to ASYNC_POOL in case parallelism disabled.