1 // Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL]
9 * A background thread. All threads created with <tt>xwt.thread</tt>
10 * are instances of this class. ThreadMessage objects can be enqueued
13 * INVARIANT: only one thread can be executing JavaScript scripts or
14 * accessing Box instances at any given time. For
15 * performance reasons, no locks are employed to enforce
18 public class ThreadMessage extends Thread implements Message {
20 public static boolean fakeBackground = false;
22 private volatile static int threadcount = 0;
24 /** the JavaScript function that we are executing */
25 volatile JS.Callable f;
27 /** the ThreadMessage thread blocks on this before executing any JavaScript */
28 Semaphore go = new Semaphore();
30 /** The Message.Q (main) thread blocks on this while the ThreadMessage thread is running JavaScript code */
31 Semaphore done = new Semaphore();
33 /** used to pool ThreadMessages that are not in use */
34 private static Queue spare = new Queue(50);
36 /** queue of functions waiting to be spawned; used if threadcount == Platform.maxThreads() */
37 private static Queue waiting = new Queue(50);
39 private ThreadMessage() { start(); }
40 private static Object[] emptyobj = new Object[] { };
42 /** creates a new thread to execute function <tt>f</tt> */
43 public static synchronized void newthread(JS.Callable f) {
44 ThreadMessage ret = (ThreadMessage)spare.remove(false);
46 if (threadcount < Platform.maxThreads()) ret = new ThreadMessage();
56 /** attempts to put this thread into the background to perform a blocking operation; returns false if unable to do so */
57 public static boolean suspendThread() {
58 if (fakeBackground) return true;
59 // put ourselves in the background
60 Thread thread = Thread.currentThread();
61 if (!(thread instanceof ThreadMessage)) {
62 if (Log.on) Log.logJS(ThreadMessage.class, "attempt to perform background-only operation in a foreground thread");
65 ThreadMessage mythread = (ThreadMessage)thread;
66 mythread.setPriority(Thread.MIN_PRIORITY);
67 mythread.done.release();
71 /** re-enqueues this thread */
72 public static void resumeThread() {
73 if (fakeBackground) return;
74 ThreadMessage mythread = (ThreadMessage)Thread.currentThread();
75 Message.Q.add(mythread);
76 mythread.setPriority(Thread.NORM_PRIORITY);
86 f.call(new JS.Array());
88 if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e);
91 synchronized(waiting) {
92 if (waiting.size() > 0) {
93 f = (JS.Callable)waiting.remove(false);
95 } else if (spare.size() < 10) {
103 } catch (Throwable t) {
104 if (Log.on) Log.log(this, "caught throwable at thread entry point; this should never happen");
105 if (Log.on) Log.log(this, t);
106 if (Log.on) Log.log(this, "reaping thread");
111 /** this is invoked in the Message.Q thread */
112 public void perform() {