All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.pincette.rs.Async Maven / Gradle / Ivy

package net.pincette.rs;

import static net.pincette.rs.Box.box;
import static net.pincette.rs.Mapper.map;
import static net.pincette.rs.Serializer.dispatch;
import static net.pincette.rs.Util.initialStageDeque;

import java.util.Deque;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Flow.Processor;
import java.util.function.Function;

/**
 * Emits the values produced by the stages in the order the stages arrive. The stream completes only
 * after the last stage has completed.
 *
 * @param  the value type.
 * @author Werner Donné
 * @since 1.5
 */
public class Async extends ProcessorBase, T> {
  private final Deque> stages = initialStageDeque();

  public static  Processor, T> async() {
    return new Async<>();
  }

  /**
   * Returns a processor with the mapping function, which transforms the objects. The completion
   * stages are processed in the order of the stream, which completes only after the last stage is
   * completed. This means the functions may start in parallel, but the completions are emitted in
   * the proper order.
   *
   * @param function the mapping function.
   * @param  the incoming value type.
   * @param  the outgoing value type.
   * @return The processor.
   * @since 3.0
   */
  public static  Processor mapAsync(final Function> function) {
    return box(map(function), async());
  }

  /**
   * Returns a processor with the mapping function, which transforms the objects. The completion
   * stages are processed in the order of the stream, which completes only after the last stage is
   * completed. The functions are executed in sequence, which means a function call starts only
   * after the previous completion stage has completed.
   *
   * @param function the mapping function.
   * @param  the incoming value type.
   * @param  the outgoing value type.
   * @return The processor.
   * @since 3.1.2
   */
  public static  Processor mapAsyncSequential(
      final Function> function) {
    return AsyncDepend.mapAsync((v, p) -> function.apply(v));
  }

  @Override
  protected void emit(final long number) {
    subscription.request(number);
  }

  @Override
  public void onComplete() {
    dispatch(
        () -> {
          if (!getError()) {
            stages.getFirst().thenRunAsync(() -> subscriber.onComplete());
          }
        });
  }

  public void onNext(final CompletionStage stage) {
    if (stage == null) {
      throw new NullPointerException("Can't emit null.");
    }

    dispatch(
        () -> {
          if (!getError()) {
            stages.addFirst(
                stages
                    .getFirst()
                    .thenComposeAsync(v -> stage.thenAccept(value -> subscriber.onNext(value)))
                    .exceptionally(
                        t -> {
                          subscriber.onError(t);
                          subscription.cancel();

                          return null;
                        }));

            while (stages.size() > 10) {
              stages.removeLast();
            }
          }
        });
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy