package org.dsa.iot.shared;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import java.util.concurrent.*;
/**
* @author Samuel Grenier
*/
public class SharedObjects {
private static final int MAX_CORE_POOL_SIZE = 64;
private static final int MIN_CORE_POOL_SIZE = 16;
private static final int CORE_POOL_FEW_PROCESSORS_THRESHOLD = 2;
private static final int CORE_POOL_MANY_PROCESSORS_MULTIPLIER = 8;
private static int calculateCorePoolSize() {
int definedSize = Integer.parseInt(System.getProperty("dsa.shared.threadPoolSize", "0"));
if (definedSize == 0) {
int processors = Runtime.getRuntime().availableProcessors();
if (processors <= CORE_POOL_FEW_PROCESSORS_THRESHOLD) {
definedSize = MIN_CORE_POOL_SIZE;
} else {
definedSize = Math.min(MAX_CORE_POOL_SIZE, processors * CORE_POOL_MANY_PROCESSORS_MULTIPLIER);
}
}
return definedSize;
}
public static final int POOL_SIZE = calculateCorePoolSize();
private static volatile ScheduledThreadPoolExecutor THREAD_POOL;
private static volatile ScheduledThreadPoolExecutor DAEMON_THREAD_POOL;
private static volatile EventLoopGroup LOOP;
public static EventLoopGroup getLoop() {
if (LOOP == null) {
LOOP = new NioEventLoopGroup();
}
return LOOP;
}
public static void setLoop(EventLoopGroup group) {
LOOP = group;
}
public static ScheduledThreadPoolExecutor createThreadPool(int size) {
return new ScheduledThreadPool(size);
}
public static ScheduledThreadPoolExecutor getThreadPool() {
if (THREAD_POOL == null) {
setThreadPool(createThreadPool(POOL_SIZE));
}
return THREAD_POOL;
}
public static void setThreadPool(ScheduledThreadPoolExecutor stpe) {
THREAD_POOL = stpe;
}
public static ScheduledThreadPoolExecutor createDaemonThreadPool(int size) {
ThreadFactory factory = getDaemonFactory();
return new ScheduledThreadPool(size, factory);
}
public static ScheduledThreadPoolExecutor getDaemonThreadPool() {
if (DAEMON_THREAD_POOL == null) {
setDaemonThreadPool(createDaemonThreadPool(POOL_SIZE));
}
return DAEMON_THREAD_POOL;
}
public static void setDaemonThreadPool(ScheduledThreadPoolExecutor stpe) {
DAEMON_THREAD_POOL = stpe;
}
private static ThreadFactory getDaemonFactory() {
return new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
};
}
protected static class ScheduledThreadPool extends ScheduledThreadPoolExecutor {
public ScheduledThreadPool(int corePoolSize) {
super(corePoolSize);
configurePolicies();
}
public ScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {
super(corePoolSize, threadFactory);
configurePolicies();
}
private void configurePolicies() {
setRemoveOnCancelPolicy(true);
setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
}
@Override
protected void afterExecute(Runnable runnable, Throwable t) {
if (t == null && runnable instanceof Future<?>) {
try {
((Future<?>) runnable).get(0, TimeUnit.NANOSECONDS);
} catch (CancellationException
| InterruptedException
| TimeoutException ignored) {
} catch (ExecutionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
throw new RuntimeException(e.getCause());
}
} else if (t != null) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
}
}
}