package cz.cuni.lf1.lge.ThunderSTORM.util;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* santiwk at stackoverflow.com
*/
public class Loop {
private static final int CPUs = Runtime.getRuntime().availableProcessors();
//private static ExecutorService executor = Executors.newCachedThreadPool();
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(CPUs, CPUs, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
public static ThreadPoolExecutor getExecutor() {
return executor;
}
static {
executor.allowCoreThreadTimeOut(true);
}
public interface BodyWithIndex {
void run(int i);
}
public static void withIndex(int start, int stop, final BodyWithIndex body) {
int chunksize = MathProxy.max((stop - start + CPUs - 1) / CPUs, 1);
int loops = (stop - start + chunksize - 1) / chunksize;
Future<?>[] futures = new Future<?>[loops];
int fi = 0;
for(int i = start; i < stop;) {
final int lo = i;
i += chunksize;
final int hi = (i < stop) ? i : stop;
futures[fi++] = executor.submit(new Runnable() {
@Override
public void run() {
for(int i = lo; i < hi; i++) {
body.run(i);
}
}
});
}
//gather any exceptions
RuntimeException t = null;
Error e = null;
for(Future<?> f : futures) {
try {
f.get();
} catch(InterruptedException ex) {
} catch(ExecutionException ex) {
if(ex.getCause() instanceof RuntimeException) {
t = (RuntimeException) ex.getCause();
}
if(ex.getCause() instanceof Error) {
e = (Error) ex.getCause();
}
}
}
if(t != null) {
throw t;
}
if(e != null) {
throw e;
}
}
public static void shutdown() {
executor.shutdown();
}
}