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