1
2 package org.xwt;
3
4 import java.util.*;
5 import org.xwt.util.*;
6 import org.xwt.js.*;
7
8
18 public class ThreadMessage extends Thread implements Message {
19
20 private volatile static int threadcount = 0;
21
22
23 volatile JS.Callable f;
24
25
26 Semaphore go = new Semaphore();
27
28
29 Semaphore done = new Semaphore();
30
31
32 private static Queue spare = new Queue(50);
33
34
35 private static Queue waiting = new Queue(50);
36
37 private ThreadMessage() { start(); }
38 private static Object[] emptyobj = new Object[] { };
39
40
41 public static synchronized void newthread(JS.Callable f) {
42 ThreadMessage ret = (ThreadMessage)spare.remove(false);
43 if (ret == null) {
44 if (threadcount < Platform.maxThreads()) ret = new ThreadMessage();
45 else {
46 waiting.append(f);
47 return;
48 }
49 }
50 ret.f = f;
51 Message.Q.add(ret);
52 }
53
54
55 public static boolean suspendThread() {
56
57 Thread thread = Thread.currentThread();
58 if (!(thread instanceof ThreadMessage)) {
59 if (Log.on) Log.logJS(ThreadMessage.class, "attempt to perform background-only operation in a foreground thread");
60 return false;
61 }
62 ThreadMessage mythread = (ThreadMessage)thread;
63 mythread.setPriority(Thread.MIN_PRIORITY);
64 mythread.done.release();
65 return true;
66 }
67
68
69 public static void resumeThread() {
70 ThreadMessage mythread = (ThreadMessage)Thread.currentThread();
71 Message.Q.add(mythread);
72 mythread.setPriority(Thread.NORM_PRIORITY);
73 mythread.go.block();
74 }
75
76 public void run() {
77 try {
78 threadcount++;
79 while (true) {
80 try {
81 go.block();
82 f.call(new JS.Array());
83 } catch (JS.Exn e) {
84 if (Log.on) Log.log(this, "WARNING: uncaught ecmascript exception: " + e);
85 }
86 done.release();
87 synchronized(waiting) {
88 if (waiting.size() > 0) {
89 f = (JS.Callable)waiting.remove(false);
90 Message.Q.add(this);
91 } else if (spare.size() < 10) {
92 spare.append(this);
93 } else {
94 threadcount--;
95 return;
96 }
97 }
98 }
99 } catch (Throwable t) {
100 if (Log.on) Log.log(this, "caught throwable at thread entry point; this should never happen");
101 if (Log.on) Log.log(this, t);
102 if (Log.on) Log.log(this, "reaping thread");
103 return;
104 }
105 }
106
107
108 public void perform() {
109 go.release();
110 done.block();
111 }
112
113 }
114