X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=blobdiff_plain;f=src2%2Fjavajs%2Futil%2FJSThread.java;fp=src2%2Fjavajs%2Futil%2FJSThread.java;h=be94c0031d898a7835d0aa58676708b08fe6adbc;hp=0000000000000000000000000000000000000000;hb=665d2c2f4c1310e6985b93b7c2c8a8eec2fa9086;hpb=0e684f72690bd6532272a39ab6c188a27559fd09 diff --git a/src2/javajs/util/JSThread.java b/src2/javajs/util/JSThread.java new file mode 100644 index 0000000..be94c00 --- /dev/null +++ b/src2/javajs/util/JSThread.java @@ -0,0 +1,216 @@ +package javajs.util; + +import java.awt.Toolkit; +import java.awt.event.InvocationEvent; + +//import javajs.J2SRequireImport; +import javajs.api.JSFunction; + + +/** + * An abstract class that takes care of simple threading in Java or JavaScript. + * + * To use it, subclass it and complete the necessary methods. + * + * + * There are three states: INIT, LOOP, and DONE. + * + * These states are passed into run1 + * + * + * @author Bob Hanson + * + */ +//@J2SRequireImport(swingjs.JSToolkit.class) +public abstract class JSThread extends Thread implements JSFunction { + + public static final int INIT = 0; + public static final int LOOP = 1; + public static final int DONE = 2; + + public static int threadCount = 0; + + protected boolean isJS; + + public JSThread() { + this(null, "JSThread-" + (++threadCount)); + } + + public JSThread(String name) { + this(null, name); + } + + public JSThread(ThreadGroup group, String name) { + super(group, name); + /** + * @j2sNative + * + * this.isJS = true; + */ + {} + } + + @Override + public void run() { + run1(INIT); + } + + @Override + public synchronized void start() { + + + /** + * @j2sNative + * + * Clazz.load("swingjs.JSToolkit").dispatch$O$I$I(this, 1, 0); + * + */ + { + super.start(); + } + + } + + /** + * thread initialization + * + * @return false to exit thread before any looping + */ + protected abstract boolean myInit(); + + /** + * check for continuing to loop + * + * @return true if we are to continue looping + */ + protected abstract boolean isLooping(); + + /** + * + * @return false to handle sleepAndReturn yourself + */ + protected abstract boolean myLoop(); + /** + * what to do when the DONE state is reached + * + */ + protected abstract void whenDone(); + + /** + * + * @return the sleep time in milliseconds + */ + protected abstract int getDelayMillis(); + + /** + * handle an exception -- state will be set to DONE no matter what you do here + * + * @param e + */ + protected abstract void onException(Exception e); + + /** + * anything you want done in try{}catch(}finally(). + * Note that this method is not fired if we are in JavaScript + * mode and the normal return from sleepAndReturn() is taken. + * + */ + protected abstract void doFinally(); + + /** + * a generic method that loops until done, either in Java or JavaScript. + * + * In JavaScript it will reenter and continue at the appropriate spot. + * + * This method may be overridden if desired. + * + * @see org.uwi.SimThread + * + * @param state + */ + protected void run1(int state) { + boolean executeFinally = true; + // called by thisThread.run(); + try { + while (!interrupted()) { + switch (state) { + case INIT: + if (!myInit()) + return; + // initial code here + state = LOOP; + continue; + case LOOP: + // to stop looping, return false from isLooping() + if (!isLooping()) { + state = DONE; + continue; + } + // To handle sleepAndReturn yourself, or to skip the + // sleep when desired, return false from myLoop(); + // Note that doFinally must not be executed in this case. + // This is because JavaScript will do a return here + // for every loop, and Java will not. + if (myLoop() && sleepAndReturn(getDelayMillis(), state)) { + executeFinally = false; + return; + } + continue; + case DONE: + whenDone(); + // whatever + return; + } + } + } catch (Exception e) { + onException(e); + state = DONE; + } finally { + if (executeFinally) + doFinally(); + } + // normal exit + } + + /** + * + * @param r2 + * @param state + * @return true if we should interrupt (i.e. JavaScript) + * @throws InterruptedException + */ + protected boolean sleepAndReturn(final int delay, final int state) + throws InterruptedException { + if (!isJS) { + sleep(delay); + return false; + } + + // in JavaScript, we need to do this through the system event queue, + // which in JSToolkit takes care of all the "thread" handling. + + final JSThread me = this; + Runnable r = new Runnable() { + @Override + public void run() { + me.run1(state); + } + }; + /** + * @j2sNative + * + * setTimeout( + * function() { + * java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent$java_awt_AWTEvent( + * Clazz.new_(java.awt.event.InvocationEvent.c$$O$Runnable,[me, r]))}, + * delay); + * + */ + { + Toolkit.getDefaultToolkit().getSystemEventQueue() + .postEvent(new InvocationEvent(me, r)); + } + return true; + } + +}