/**
TrakEM2 plugin for ImageJ(C).
Copyright (C) 2008-2009 Albert Cardona.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation (http://www.gnu.org/licenses/gpl.txt )
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You may contact Albert Cardona at acardona at ini.phys.ethz.ch
Institute of Neuroinformatics, University of Zurich / ETH, Switzerland.
**/
package ini.trakem2.utils;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.SwingUtilities;
public class Dispatcher {
private final class Task implements Runnable {
final Runnable run;
final boolean swing;
private Task(final Runnable run, final boolean swing) {
this.run = run;
this.swing = swing;
}
public void run() {
try {
if (swing) SwingUtilities.invokeAndWait(run);
else run.run();
} catch (InterruptedException ie) {
Utils.log2("Sayonara!");
// buh! If the EDT dies, JVM is shutting down.
// If the dispatcher dies, it's been killed.
} catch (Throwable e) {
IJError.print(e);
}
}
}
private final ExecutorService exec;
static public class DispatcherThreadFactory implements ThreadFactory {
final ThreadGroup group;
final String tag;
public DispatcherThreadFactory(final String tag) {
this.tag = tag;
final SecurityManager s = System.getSecurityManager();
this.group = (null != s) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
}
final public Thread newThread(final Runnable r) {
final Thread t = new CachingThread(group, r, tag);
if (t.isDaemon()) t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
public Dispatcher(final String tag) {
this.exec = new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
new DispatcherThreadFactory("T2-Dispatcher" + (null != tag ? " " + tag : "")));
}
public Dispatcher() {
this(null);
}
public void quit() {
exec.shutdownNow();
}
public boolean isQuit() {
return exec.isShutdown();
}
public void quitWhenDone() {
exec.shutdown(); // orderly shutdown, in which no more tasks are accepted for execution, but remaining tasks are executed.
}
/** Submits the task for execution and returns immediately. */
public void exec(final Runnable run) { exec(run, false); }
public void execSwing(final Runnable run) { exec(run, true); }
public void exec(final Runnable run, final boolean swing) {
if (exec.isShutdown()) {
Utils.log2("Dispatcher: NOT accepting more tasks!");
return;
}
exec.submit(new Task(run, swing));
}
}