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