package org.intellimate.izou.util;
import ro.fortsoft.pf4j.AddonAccessible;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* ALWAYS implement this interface when you have to put some Tasks into the ThreadPool
* @author Leander Kurscheidt
* @version 1.0
*/
@AddonAccessible
public interface AddonThreadPoolUser extends MainProvider {
/**
* submits the Runnable to the AddOns Thread-Pool
* @param runnable the runnable to submit
* @return the new CompletableFuture
*/
default CompletableFuture<Void> submit(Runnable runnable) {
return CompletableFuture.runAsync(runnable, getMain().getThreadPoolManager().getAddOnsThreadPool())
.whenComplete((u, ex) -> {
if (ex != null) {
getMain().getThreadPoolManager().handleThrowable(ex, runnable);
}
});
}
/**
* submits the Supplier to the AddOns Thread-Pool
* @param supplier the supplier executed
* @param <U> the return type
* @return the new CompletableFuture
*/
default <U> CompletableFuture<U> submit(Supplier<U> supplier) {
return CompletableFuture.supplyAsync(supplier, getMain().getThreadPoolManager().getAddOnsThreadPool())
.whenComplete((u, ex) -> {
if (ex != null) {
getMain().getThreadPoolManager().handleThrowable(ex, supplier);
}
});
}
/**
* times out the collection of futures
* @param futures the collection of futures
* @param milliseconds the limit in milliseconds (everything under 20 milliseconds makes no sense)
* @param <U> the return type of the futures
* @param <V> the type of the futures
* @return a List of futures
* @throws InterruptedException if the process was interrupted
*/
default <U, V extends Future<U>> List<V> timeOut(Collection<? extends V> futures,
int milliseconds) throws InterruptedException {
// Track timeout
Instant start = Instant.now();
long duration = 0;
boolean notFinished = true;
while ( (duration < milliseconds) && notFinished) {
notFinished = futures.stream()
.anyMatch(future -> !future.isDone());
duration = Instant.now().toEpochMilli() - start.toEpochMilli();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw e;
}
}
//cancel all running tasks
if(notFinished) {
futures.stream()
.filter(future -> !future.isDone())
.peek(future -> error(future.toString()+ " timed out",
new Exception(future.toString() + " timed out")))
.forEach(future -> future.cancel(true));
}
return futures.stream()
.filter(Future::isDone)
.collect(Collectors.<V>toList());
}
}