package nl.tudelft.simulation.language.swing; import javax.swing.SwingUtilities; /** * This is the 3rd version of SwingWorker (also known as SwingWorker 3), an abstract class that you subclass to perform * GUI-related work in a dedicated thread. For instructions on and examples of using this class, see: * * https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html . Note that the API changed slightly in * the 3rd version: You must now invoke start() on the SwingWorker after creating it. *

* Copyright (c) 2002-2019 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights * reserved. See for project information * https://simulation.tudelft.nl. The DSOL project is distributed under a three-clause BSD-style license, which can * be found at * https://simulation.tudelft.nl/dsol/3.0/license.html. *

*/ public abstract class SwingWorker { /** the value of the worker. */ private Object value; // see getValue(), setValue() /** the thread to use. */ protected ThreadVar threadVar; /** * @return Get the value produced by the worker thread, or null if it hasn't been constructed yet. */ protected synchronized Object getValue() { return this.value; } /** * Set the value produced by worker thread * @param x Object; the value */ protected synchronized void setValue(final Object x) { this.value = x; } /** * @return Compute the value to be returned by the get method. */ public abstract Object construct(); /** * Called on the event dispatching thread (not on the worker thread) after the construct method has * returned. */ public void finished() { // Nothing to be done. } /** * A new method that interrupts the worker thread. Call this method to force the worker to stop what it's doing. */ public void interrupt() { Thread t = this.threadVar.get(); if (t != null) { t.interrupt(); } this.threadVar.clear(); } /** * Return the value created by the construct method. Returns null if either the constructing thread or * the current thread was interrupted before a value was produced. * @return the value created by the construct method */ public Object get() { while (true) { Thread t = this.threadVar.get(); if (t == null) { return getValue(); } try { t.join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // propagate return null; } } } /** * Start a thread that will call the construct method and then exit. */ public SwingWorker() { final Runnable doFinished = new Runnable() { @Override public void run() { finished(); } }; Runnable doConstruct = new Runnable() { @Override public void run() { try { SwingWorker.this.setValue(construct()); } finally { SwingWorker.this.threadVar.clear(); } SwingUtilities.invokeLater(doFinished); } }; Thread t = new Thread(doConstruct); this.threadVar = new ThreadVar(t); } /** * Start the worker thread. */ public void start() { Thread t = this.threadVar.get(); if (t != null) { t.start(); } } /** * Class to maintain reference to current worker thread under separate synchronization control. */ private static class ThreadVar { /** the thread to use. */ private Thread thread; /** * constructs a new ThreadVar. * @param t Thread; the thread */ ThreadVar(final Thread t) { this.thread = t; } /** * returns the thread * @return Thread the thread */ synchronized Thread get() { return this.thread; } /** * clears the thread */ synchronized void clear() { this.thread = null; } } }