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

io.atomix.copycat.client.util.OrderedCompletableFuture Maven / Gradle / Ivy

There is a newer version: 1.2.8
Show newest version
package io.atomix.copycat.client.util;

import io.atomix.catalyst.concurrent.Futures;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * A {@link CompletableFuture} that ensures callbacks are called in FIFO order.
 * 

* The default {@link CompletableFuture} does not guarantee the ordering of callbacks, and indeed appears to * execute them in LIFO order. */ public class OrderedCompletableFuture extends CompletableFuture { private final Queue> orderedFutures = new LinkedList<>(); private boolean complete; private T result; private Throwable error; public OrderedCompletableFuture() { super.whenComplete(this::complete); } /** * Adds a new ordered future. */ private CompletableFuture orderedFuture() { synchronized (orderedFutures) { if (complete) { if (error == null) { return CompletableFuture.completedFuture(result); } else { return Futures.exceptionalFuture(error); } } else { CompletableFuture future = new CompletableFuture<>(); orderedFutures.add(future); return future; } } } /** * Completes futures in FIFO order. */ private void complete(T result, Throwable error) { synchronized (orderedFutures) { this.complete = true; this.result = result; this.error = error; if (error == null) { for (CompletableFuture future : orderedFutures) { future.complete(result); } } else { for (CompletableFuture future : orderedFutures) { future.completeExceptionally(error); } } } } @Override public CompletableFuture thenApply(Function fn) { return orderedFuture().thenApply(fn); } @Override public CompletableFuture thenApplyAsync(Function fn) { return orderedFuture().thenApplyAsync(fn); } @Override public CompletableFuture thenApplyAsync(Function fn, Executor executor) { return orderedFuture().thenApplyAsync(fn, executor); } @Override public CompletableFuture thenAccept(Consumer action) { return orderedFuture().thenAccept(action); } @Override public CompletableFuture thenAcceptAsync(Consumer action) { return orderedFuture().thenAcceptAsync(action); } @Override public CompletableFuture thenAcceptAsync(Consumer action, Executor executor) { return orderedFuture().thenAcceptAsync(action, executor); } @Override public CompletableFuture thenRun(Runnable action) { return orderedFuture().thenRun(action); } @Override public CompletableFuture thenRunAsync(Runnable action) { return orderedFuture().thenRunAsync(action); } @Override public CompletableFuture thenRunAsync(Runnable action, Executor executor) { return orderedFuture().thenRunAsync(action, executor); } @Override public CompletableFuture thenCombine(CompletionStage other, BiFunction fn) { return orderedFuture().thenCombine(other, fn); } @Override public CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn) { return orderedFuture().thenCombineAsync(other, fn); } @Override public CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor) { return orderedFuture().thenCombineAsync(other, fn, executor); } @Override public CompletableFuture thenAcceptBoth(CompletionStage other, BiConsumer action) { return orderedFuture().thenAcceptBoth(other, action); } @Override public CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action) { return orderedFuture().thenAcceptBothAsync(other, action); } @Override public CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor) { return orderedFuture().thenAcceptBothAsync(other, action, executor); } @Override public CompletableFuture runAfterBoth(CompletionStage other, Runnable action) { return orderedFuture().runAfterBoth(other, action); } @Override public CompletableFuture runAfterBothAsync(CompletionStage other, Runnable action) { return orderedFuture().runAfterBothAsync(other, action); } @Override public CompletableFuture runAfterBothAsync(CompletionStage other, Runnable action, Executor executor) { return orderedFuture().runAfterBothAsync(other, action, executor); } @Override public CompletableFuture applyToEither(CompletionStage other, Function fn) { return orderedFuture().applyToEither(other, fn); } @Override public CompletableFuture applyToEitherAsync(CompletionStage other, Function fn) { return orderedFuture().applyToEitherAsync(other, fn); } @Override public CompletableFuture applyToEitherAsync(CompletionStage other, Function fn, Executor executor) { return orderedFuture().applyToEitherAsync(other, fn, executor); } @Override public CompletableFuture acceptEither(CompletionStage other, Consumer action) { return orderedFuture().acceptEither(other, action); } @Override public CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action) { return orderedFuture().acceptEitherAsync(other, action); } @Override public CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action, Executor executor) { return orderedFuture().acceptEitherAsync(other, action, executor); } @Override public CompletableFuture runAfterEither(CompletionStage other, Runnable action) { return orderedFuture().runAfterEither(other, action); } @Override public CompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action) { return orderedFuture().runAfterEitherAsync(other, action); } @Override public CompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor) { return orderedFuture().runAfterEitherAsync(other, action, executor); } @Override public CompletableFuture thenCompose(Function> fn) { return orderedFuture().thenCompose(fn); } @Override public CompletableFuture thenComposeAsync(Function> fn) { return orderedFuture().thenComposeAsync(fn); } @Override public CompletableFuture thenComposeAsync(Function> fn, Executor executor) { return orderedFuture().thenComposeAsync(fn, executor); } @Override public CompletableFuture whenComplete(BiConsumer action) { return orderedFuture().whenComplete(action); } @Override public CompletableFuture whenCompleteAsync(BiConsumer action) { return orderedFuture().whenCompleteAsync(action); } @Override public CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) { return orderedFuture().whenCompleteAsync(action, executor); } @Override public CompletableFuture handle(BiFunction fn) { return orderedFuture().handle(fn); } @Override public CompletableFuture handleAsync(BiFunction fn) { return orderedFuture().handleAsync(fn); } @Override public CompletableFuture handleAsync(BiFunction fn, Executor executor) { return orderedFuture().handleAsync(fn, executor); } @Override public CompletableFuture exceptionally(Function fn) { return orderedFuture().exceptionally(fn); } @Override public CompletableFuture toCompletableFuture() { return this; } }