org.infinispan.commons.util.concurrent.CompositeNotifyingFuture Maven / Gradle / Ivy
package org.infinispan.commons.util.concurrent;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* CompositeNotifyingFuture aggregates several NotifyingFuture and completes when all of them complete.
*
* @author gustavonalle
* @since 7.1
*/
public final class CompositeNotifyingFuture extends NotifyingFutureImpl {
private final CountDownLatch remaining;
private final List> futures;
private volatile boolean cancelled = false;
public CompositeNotifyingFuture(List> futures) {
this.futures = futures;
this.remaining = new CountDownLatch(futures.size());
InternalListener internalListener = new InternalListener();
for (NotifyingFuture future : futures) {
future.attachListener(internalListener);
}
}
@Override
public boolean isDone() {
return remaining.getCount() == 0;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
this.cancelled = true;
boolean wasCancelled = true;
for (NotifyingFuture> future : futures) {
wasCancelled &= future.cancel(mayInterruptIfRunning);
}
return wasCancelled;
}
@Override
public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null) throw new IllegalArgumentException("provided unit is null");
if (cancelled) throw new CancellationException();
if (!remaining.await(timeout, unit)) throw new TimeoutException();
return super.get();
}
@Override
public Void get() throws InterruptedException, ExecutionException {
if (cancelled) throw new CancellationException();
remaining.await();
return super.get();
}
final class InternalListener implements FutureListener {
@Override
public void futureDone(Future future) {
synchronized (this) {
Throwable error = null;
try {
future.get();
} catch (Throwable e) {
error = e;
}
remaining.countDown();
if (remaining.getCount() == 0) {
setFuture(new NoOpFuture(null));
if (error != null) {
notifyException(error);
} else {
notifyDone(null);
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy