1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.microemu.app.util;
28
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.WeakHashMap;
32
33 import org.microemu.MIDletBridge;
34 import org.microemu.MIDletContext;
35 import org.microemu.log.Logger;
36 import org.microemu.util.ThreadUtils;
37
38
39
40
41
42
43 public class MIDletThread extends Thread {
44
45 public static int graceTerminationPeriod = 5000;
46
47 private static final String THREAD_NAME_PREFIX = "MIDletThread-";
48
49 private static boolean terminator = false;
50
51 private static Map midlets = new WeakHashMap();
52
53 private static int threadInitNumber;
54
55 private String callLocation;
56
57 private static synchronized int nextThreadNum() {
58 return threadInitNumber++;
59 }
60
61 public MIDletThread() {
62 super(THREAD_NAME_PREFIX + nextThreadNum());
63 register(this);
64 }
65
66 public MIDletThread(Runnable target) {
67 super(target, THREAD_NAME_PREFIX + nextThreadNum());
68 register(this);
69 }
70
71 public MIDletThread(Runnable target, String name) {
72 super(target, THREAD_NAME_PREFIX + name);
73 register(this);
74 }
75
76 public MIDletThread(String name) {
77 super(THREAD_NAME_PREFIX + name);
78 register(this);
79 }
80
81 private static void register(MIDletThread thread) {
82 MIDletContext midletContext = MIDletBridge.getMIDletContext();
83 if (midletContext == null) {
84 Logger.error("Creating thread with no MIDlet context", new Throwable());
85 return;
86 }
87 thread.callLocation = ThreadUtils.getCallLocation(MIDletThread.class.getName());
88 Map threads = (Map)midlets.get(midletContext);
89 if (threads == null) {
90 threads = new WeakHashMap();
91 midlets.put(midletContext, threads);
92 }
93 threads.put(thread, midletContext);
94 }
95
96
97 public void run() {
98 try {
99 super.run();
100 } catch (Throwable e) {
101 Logger.debug("MIDletThread throw", e);
102 }
103
104 }
105
106
107
108
109
110 public static void contextDestroyed(final MIDletContext midletContext) {
111 if (midletContext == null) {
112 return;
113 }
114 final Map threads = (Map)midlets.remove(midletContext);
115 if ((threads != null) && (threads.size() != 0)) {
116 terminator = true;
117 Thread terminator = new Thread("MIDletThreadsTerminator") {
118 public void run() {
119 terminateThreads(threads);
120 }
121 };
122 terminator.start();
123 }
124 MIDletTimer.contextDestroyed(midletContext);
125 }
126
127 public static boolean hasRunningThreads(MIDletContext midletContext) {
128
129 return terminator;
130 }
131
132 private static void terminateThreads(Map threads) {
133 long endTime = System.currentTimeMillis() + graceTerminationPeriod;
134 for (Iterator iter = threads.keySet().iterator(); iter.hasNext();) {
135 Object o = iter.next();
136 if (o == null) {
137 continue;
138 }
139 if (o instanceof MIDletThread) {
140 MIDletThread t = (MIDletThread) o;
141 if (t.isAlive()) {
142 Logger.info("wait thread [" + t.getName() + "] end");
143 while ((endTime > System.currentTimeMillis()) && (t.isAlive())) {
144 try {
145 t.join(700);
146 } catch (InterruptedException e) {
147 break;
148 }
149 }
150 if (t.isAlive()) {
151 Logger.warn("MIDlet thread [" + t.getName() + "] still running" + ThreadUtils.getTreadStackTrace(t));
152 if (t.callLocation != null) {
153 Logger.info("this thread [" + t.getName() + "] was created from " + t.callLocation);
154 }
155 t.interrupt();
156 }
157 }
158 } else {
159 Logger.debug("unrecognized Object [" + o.getClass().getName() + "]");
160 }
161 };
162 Logger.debug("all "+ threads.size() + " thread(s) finished");
163 terminator = false;
164 }
165
166 }