001package org.intellimate.izou.threadpool;
002
003import org.intellimate.izou.util.IzouModule;
004import org.intellimate.izou.main.Main;
005
006import java.lang.reflect.Field;
007import java.util.concurrent.*;
008
009/**
010 * contains all the ThreadPools.
011 * @author LeanderK
012 * @version 1.0
013 */
014public class ThreadPoolManager extends IzouModule {
015    //holds the threads
016    private final ExecutorService izouThreadPool = Executors.newCachedThreadPool(new LoggingThreadFactory());
017    //holds the threads
018    private final ExecutorService addOnsThreadPool = Executors.newCachedThreadPool(new LoggingThreadFactory());
019
020    /**
021     * creates a new ThreadPoolManager
022     * @param main instance of Main
023     */
024    public ThreadPoolManager(Main main) {
025        super(main);
026    }
027
028    /**
029     * returns the ThreadPool where all the Izou-Components are running
030     * <p>this method should only be used by IzouModules</p>
031     * @return an ExecutorService
032     */
033    public ExecutorService getIzouThreadPool() {
034        return izouThreadPool;
035    }
036
037    /**
038     * returns the ThreadPool where all the AddOns are running
039     * @return an ExecutorService
040     */
041    public ExecutorService getAddOnsThreadPool() {
042        return addOnsThreadPool;
043    }
044
045    /**
046     * tries everything to log the exception
047     * @param e the Throwable
048     * @param target an instance of the thing which has thrown the Exception
049     */
050    public void handleThrowable(Throwable e, Object target) {
051        try {
052            ExceptionCallback exceptionCallback = (ExceptionCallback) target;
053            if (e instanceof Exception) {
054                exceptionCallback.exceptionThrown((Exception) e);
055            } else {
056                exceptionCallback.exceptionThrown(new RuntimeException(e));
057            }
058        } catch (IllegalArgumentException | ClassCastException e1) {
059            log.fatal("unable to provide callback for: " + target.toString(), e);
060        }
061    }
062
063    /**
064     * used to catch Exception in threads
065     */
066    private class LoggingThreadFactory implements ThreadFactory {
067        @SuppressWarnings("NullableProblems")
068        @Override
069        public Thread newThread(Runnable r) {
070            Thread t = new Thread() {
071                public void run() {
072                    try {
073                        r.run();
074                    } catch (Exception | LinkageError e) {
075                        try {
076                            Field target = Thread.class.getDeclaredField("target");
077                            target.setAccessible(true);
078                            try {
079                                handleThrowable(e, target.get(this));
080                            } catch (IllegalAccessException e1) {
081                                log.fatal("unable to provide callback for: " + target.toString(), e);
082                            }
083                        } catch (NoSuchFieldException e1) {
084                            log.fatal(e);
085                        }
086                    }
087                }
088            };
089            t.setPriority(Thread.MIN_PRIORITY);
090            return t;
091        }
092    }
093}