content: package mars.simulator;
  
  import javax.swing.SwingUtilities;
  
  /*-----------------------------------------------------
   * This file downloaded from the Sun Microsystems URL given below.
   *
   * I will subclass it to create worker thread for running
   * MIPS simulated execution.
   */
  
  /**
   * 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:
   * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html Note that
   * the API changed slightly in the 3rd version: You must now invoke start() on
   * the SwingWorker after creating it.
   */
  public abstract class SwingWorker {
  
  	private Object value;  // see getValue(), setValue()
  
  	/**
  	 * Class to maintain reference to current worker thread under separate
  	 * synchronization control.
  	 */
  	private static class ThreadVar {
  
  		private Thread thread;
  
  		ThreadVar(final Thread t) {
  			thread = t;
  		}
  
  		synchronized Thread get() {
  			return thread;
  		}
  
  		synchronized void clear() {
  			thread = null;
  		}
  	}
  
  	private ThreadVar threadVar;
  
  	/**
  	 * Get the value produced by the worker thread, or null if it hasn't been
  	 * constructed yet.
  	 */
  	protected synchronized Object getValue() { return value; }
  
  	/**
  	 * Set the value produced by worker thread
  	 */
  	private synchronized void setValue(final Object x) { value = x; }
  
  	/**
  	 * Compute the value to be returned by the <code>get</code> method.
  	 */
  	public abstract Object construct();
  
  	/**
  	 * Called on the event dispatching thread (not on the worker thread) after the
  	 * <code>construct</code> method has returned.
  	 */
  	public void finished() {}
  
  	/**
  	 * A new method that interrupts the worker thread. Call this method to force the
  	 * worker to stop what it's doing.
  	 */
  	public void interrupt() {
  		final Thread t = threadVar.get();
  		if (t != null) { t.interrupt(); }
  		threadVar.clear();
  	}
  
  	/**
  	 * Return the value created by the <code>construct</code> 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 <code>construct</code> method
  	 */
  	public Object get() {
  		while (true) {
  			final Thread t = threadVar.get();
  			if (t == null) { return getValue(); }
  			try {
  				t.join();
  			} catch (final InterruptedException e) {
  				Thread.currentThread().interrupt(); // propagate
  				return null;
  			}
  		}
  	}
  
  	/**
  	 * Start a thread that will call the <code>construct</code> method and then
  	 * exit.
  	 *
  	 * @param useSwing Set true if MARS is running from GUI, false otherwise.
  	 */
  	public SwingWorker(final boolean useSwing) {
  		final Runnable doFinished = () -> finished();
  
  		final Runnable doConstruct = () -> {
  			try {
  				setValue(construct());
  			} finally {
  				threadVar.clear();
  			}
  
  			if (useSwing) {
  				SwingUtilities.invokeLater(doFinished);
  			} else {
  				doFinished.run();
  			}
  		};
  
  		// Thread that represents executing MIPS program...
  		final Thread t = new Thread(doConstruct, "MIPS");
  
  		//t.setPriority(Thread.NORM_PRIORITY-1);//******************
  
  		threadVar = new ThreadVar(t);
  	}
  
  	/**
  	 * Start the worker thread.
  	 */
  	public void start() {
  		final Thread t = threadVar.get();
  		if (t != null) { t.start(); }
  	}
  }
  