aboutsummaryrefslogtreecommitdiffstats
path: root/jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java
Publish
Diffstat (limited to 'jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java')
-rw-r--r--jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java97
1 files changed, 97 insertions, 0 deletions
diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java b/jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java
new file mode 100644
index 00000000000..eebb0ea266b
--- /dev/null
+++ b/jdisc_core/src/main/java/com/yahoo/jdisc/handler/FutureConjunction.java
@@ -0,0 +1,97 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.jdisc.handler;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * <p>This class implements a Future&lt;Boolean&gt; that is conjunction of zero or more other Future&lt;Boolean&gt;s,
+ * i.e. it evaluates to <tt>true</tt> if, and only if, all its operands evaluate to <tt>true</tt>. To use this class,
+ * simply create an instance of it and add operands to it using the {@link #addOperand(ListenableFuture)} method.</p>
+ * TODO: consider rewriting usage of FutureConjunction to use CompletableFuture instead.
+ *
+ * @author <a href="mailto:simon@yahoo-inc.com">Simon Thoresen</a>
+ */
+public final class FutureConjunction implements ListenableFuture<Boolean> {
+
+ private final List<ListenableFuture<Boolean>> operands = new LinkedList<>();
+
+ /**
+ * <p>Adds a ListenableFuture&lt;Boolean&gt; to this conjunction. This can be called at any time, even after having called
+ * {@link #get()} previously.</p>
+ *
+ * @param operand The operand to add to this conjunction.
+ */
+ public void addOperand(ListenableFuture<Boolean> operand) {
+ operands.add(operand);
+ }
+
+ @Override
+ public void addListener(Runnable listener, Executor executor) {
+ Futures.allAsList(operands).addListener(listener, executor);
+ }
+
+ @Override
+ public final boolean cancel(boolean mayInterruptIfRunning) {
+ boolean ret = true;
+ for (Future<Boolean> op : operands) {
+ if (!op.cancel(mayInterruptIfRunning)) {
+ ret = false;
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public final boolean isCancelled() {
+ for (Future<Boolean> op : operands) {
+ if (!op.isCancelled()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final boolean isDone() {
+ for (Future<Boolean> op : operands) {
+ if (!op.isDone()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final Boolean get() throws InterruptedException, ExecutionException {
+ Boolean ret = Boolean.TRUE;
+ for (Future<Boolean> op : operands) {
+ if (!op.get()) {
+ ret = Boolean.FALSE;
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public final Boolean get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
+ TimeoutException {
+ Boolean ret = Boolean.TRUE;
+ long nanos = unit.toNanos(timeout);
+ long lastTime = System.nanoTime();
+ for (Future<Boolean> op : operands) {
+ if (!op.get(nanos, TimeUnit.NANOSECONDS)) {
+ ret = Boolean.FALSE;
+ }
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ return ret;
+ }
+}