org.infinispan.executors.ExecutorAllCompletionService Maven / Gradle / Ivy
package org.infinispan.executors;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
/**
* Exectues given tasks in provided executor.
*
* @author Radim Vansa <[email protected]>
*/
public class ExecutorAllCompletionService implements CompletionService {
private ExecutorCompletionService executorService;
private AtomicReference firstException = new AtomicReference();
private AtomicLong scheduled = new AtomicLong();
private AtomicLong completed = new AtomicLong();
public ExecutorAllCompletionService(Executor executor) {
this.executorService = new ExecutorCompletionService(executor);
}
@Override
public Future submit(final Callable task) {
scheduled.incrementAndGet();
Future future = executorService.submit(task);
pollUntilEmpty();
return future;
}
@Override
public Future submit(final Runnable task, Void result) {
scheduled.incrementAndGet();
Future future = executorService.submit(task, result);
pollUntilEmpty();
return future;
}
private void pollUntilEmpty() {
Future completedFuture;
while ((completedFuture = executorService.poll()) != null) {
try {
completedFuture.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
if (firstException.get() == null) {
firstException.compareAndSet(null, e);
}
} finally {
completed.incrementAndGet();
}
}
}
/**
* @return True if all currently scheduled tasks have already been completed, false otherwise;
*/
public boolean isAllCompleted() {
pollUntilEmpty();
return completed.get() >= scheduled.get();
}
public long getScheduledTasks() {
return scheduled.get();
}
public long getCompletedTasks() {
return completed.get();
}
public void waitUntilAllCompleted() {
while (completed.get() < scheduled.get()) {
// Here is a race - if we poll the last scheduled entry elsewhere, we may wait
// another 100 ms until we realize that everything has already completed.
// Nevertheless, that's not so bad.
try {
Future future = poll(100, TimeUnit.MILLISECONDS);
if (future != null) {
future.get();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} catch (ExecutionException e) {
if (firstException.get() == null) {
firstException.compareAndSet(null, e);
}
}
}
}
public boolean isExceptionThrown() {
return firstException.get() != null;
}
public ExecutionException getFirstException() {
return firstException.get();
}
@Override
public Future take() throws InterruptedException {
Future future = executorService.take();
completed.incrementAndGet();
return future;
}
@Override
public Future poll() {
Future future = executorService.poll();
if (future != null) {
completed.incrementAndGet();
}
return future;
}
@Override
public Future poll(long timeout, TimeUnit unit) throws InterruptedException {
Future future = executorService.poll(timeout, unit);
if (future != null) {
completed.incrementAndGet();
}
return future;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy