]>
Commit | Line | Data |
---|---|---|
ee9dd372 TT |
1 | // Thread.java - Thread class. |
2 | ||
2ba5f774 | 3 | /* Copyright (C) 1998, 1999, 2000 Free Software Foundation |
ee9dd372 TT |
4 | |
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | package java.lang; | |
12 | ||
13 | /** | |
14 | * @author Tom Tromey <tromey@cygnus.com> | |
15 | * @date August 24, 1998 | |
16 | */ | |
17 | ||
18 | /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 | |
19 | * "The Java Language Specification", ISBN 0-201-63451-1 | |
20 | * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. | |
21 | * Status: Complete to version 1.1, with caveats | |
22 | * Known problems: | |
23 | * No attempt was made to implement suspend/resume | |
24 | * (this could be done in some cases) | |
25 | * Various methods which assume a VM are likewise unimplemented | |
26 | * We do implement stop() even though it is deprecated. | |
27 | */ | |
28 | ||
29 | public class Thread implements Runnable | |
30 | { | |
31 | public final static int MAX_PRIORITY = 10; | |
32 | public final static int MIN_PRIORITY = 1; | |
33 | public final static int NORM_PRIORITY = 5; | |
34 | ||
35 | public static int activeCount () | |
36 | { | |
37 | return currentThread().getThreadGroup().activeCount(); | |
38 | } | |
39 | ||
40 | public void checkAccess () | |
41 | { | |
42 | SecurityManager s = System.getSecurityManager(); | |
43 | if (s != null) | |
44 | s.checkAccess(this); | |
45 | } | |
46 | ||
47 | public native int countStackFrames (); | |
48 | public static native Thread currentThread (); | |
49 | public native void destroy (); | |
83379bef BM |
50 | |
51 | public static void dumpStack () | |
52 | { | |
53 | (new Exception ("Stack trace")).printStackTrace (); | |
54 | } | |
ee9dd372 TT |
55 | |
56 | public static int enumerate (Thread[] threads) | |
57 | { | |
58 | return currentThread().group.enumerate(threads); | |
59 | } | |
60 | ||
61 | public final String getName () | |
62 | { | |
63 | return name; | |
64 | } | |
65 | ||
66 | public final int getPriority () | |
67 | { | |
68 | return priority; | |
69 | } | |
70 | ||
71 | public final ThreadGroup getThreadGroup () | |
72 | { | |
73 | return group; | |
74 | } | |
75 | ||
76 | public native void interrupt (); | |
77 | ||
78 | public static boolean interrupted () | |
79 | { | |
b834f1fa | 80 | return currentThread().isInterrupted (true); |
ee9dd372 TT |
81 | } |
82 | ||
9310f1eb | 83 | // Check the threads interrupted status. Note that this does not clear the |
b834f1fa | 84 | // thread's interrupted status (per JDK 1.2 online API documentation). |
ee9dd372 TT |
85 | public boolean isInterrupted () |
86 | { | |
9310f1eb | 87 | return interrupt_flag; |
ee9dd372 TT |
88 | } |
89 | ||
90 | public final boolean isAlive () | |
91 | { | |
92 | return alive_flag; | |
93 | } | |
94 | ||
95 | public final boolean isDaemon () | |
96 | { | |
97 | return daemon_flag; | |
98 | } | |
99 | ||
100 | public final void join () throws InterruptedException | |
101 | { | |
102 | join (0, 0); | |
103 | } | |
104 | ||
105 | public final void join (long timeout) throws InterruptedException | |
106 | { | |
107 | join (timeout, 0); | |
108 | } | |
109 | ||
110 | public final native void join (long timeout, int nanos) | |
111 | throws InterruptedException; | |
112 | ||
113 | public final native void resume (); | |
114 | ||
115 | // This method exists only to avoid a warning from the C++ compiler. | |
b099f07d TT |
116 | private static final native void run_ (Object obj); |
117 | private final native void finish_ (); | |
9310f1eb | 118 | |
b834f1fa BM |
119 | // Check the thread's interrupted status. If clear_flag is true, the |
120 | // thread's interrupted status is also cleared. | |
121 | private boolean isInterrupted (boolean clear_flag) | |
9310f1eb BM |
122 | { |
123 | boolean r = interrupt_flag; | |
b834f1fa BM |
124 | if (clear_flag && r) |
125 | { | |
126 | // Only clear the flag if we saw it as set. Otherwise this could | |
127 | // potentially cause us to miss an interrupt in a race condition, | |
128 | // because this method is not synchronized. | |
129 | interrupt_flag = false; | |
130 | } | |
9310f1eb BM |
131 | return r; |
132 | } | |
133 | ||
ee9dd372 TT |
134 | public void run () |
135 | { | |
136 | if (runnable != null) | |
137 | runnable.run(); | |
138 | } | |
139 | ||
140 | public final void setDaemon (boolean status) | |
141 | { | |
142 | checkAccess (); | |
143 | if (isAlive ()) | |
144 | throw new IllegalThreadStateException (); | |
145 | daemon_flag = status; | |
146 | } | |
147 | ||
148 | // TODO12: | |
149 | // public ClassLoader getContextClassLoader() | |
150 | // { | |
151 | // } | |
152 | ||
153 | // TODO12: | |
154 | // public void setContextClassLoader(ClassLoader cl) | |
155 | // { | |
156 | // } | |
157 | ||
158 | public final void setName (String n) | |
159 | { | |
160 | checkAccess (); | |
161 | // The Class Libraries book says ``threadName cannot be null''. I | |
162 | // take this to mean NullPointerException. | |
163 | if (n == null) | |
164 | throw new NullPointerException (); | |
165 | name = n; | |
166 | } | |
167 | ||
168 | public final native void setPriority (int newPriority); | |
169 | ||
170 | public static void sleep (long timeout) throws InterruptedException | |
171 | { | |
172 | sleep (timeout, 0); | |
173 | } | |
174 | ||
175 | public static native void sleep (long timeout, int nanos) | |
176 | throws InterruptedException; | |
177 | public synchronized native void start (); | |
178 | ||
179 | public final void stop () | |
180 | { | |
16f39e24 TT |
181 | // Argument doesn't matter, because this is no longer |
182 | // supported. | |
183 | stop (null); | |
ee9dd372 TT |
184 | } |
185 | ||
186 | public final synchronized native void stop (Throwable e); | |
187 | public final native void suspend (); | |
188 | ||
189 | private final native void initialize_native (); | |
190 | ||
191 | private final synchronized static String gen_name () | |
192 | { | |
193 | String n; | |
194 | n = "Thread-" + nextThreadNumber; | |
195 | ++nextThreadNumber; | |
196 | return n; | |
197 | } | |
198 | ||
199 | public Thread (ThreadGroup g, Runnable r, String n) | |
200 | { | |
ee9dd372 | 201 | Thread current = currentThread (); |
6dfd8a77 BM |
202 | |
203 | if (g == null) | |
ee9dd372 | 204 | { |
6dfd8a77 BM |
205 | // If CURRENT is null, then we are bootstrapping the first thread. |
206 | // Use ThreadGroup.root, the main threadgroup. | |
207 | if (current == null) | |
208 | group = ThreadGroup.root; | |
209 | else | |
210 | group = current.getThreadGroup(); | |
ee9dd372 TT |
211 | } |
212 | else | |
6dfd8a77 BM |
213 | group = g; |
214 | ||
215 | group.checkAccess(); | |
ee9dd372 TT |
216 | |
217 | // The Class Libraries book says ``threadName cannot be null''. I | |
218 | // take this to mean NullPointerException. | |
219 | if (n == null) | |
220 | throw new NullPointerException (); | |
221 | ||
222 | name = n; | |
6dfd8a77 | 223 | group.add(this); |
ee9dd372 TT |
224 | runnable = r; |
225 | ||
226 | data = null; | |
227 | interrupt_flag = false; | |
228 | alive_flag = false; | |
b834f1fa BM |
229 | startable_flag = true; |
230 | ||
ee9dd372 TT |
231 | if (current != null) |
232 | { | |
233 | daemon_flag = current.isDaemon(); | |
6dfd8a77 BM |
234 | int gmax = group.getMaxPriority(); |
235 | int pri = current.getPriority(); | |
236 | priority = (gmax < pri ? gmax : pri); | |
ee9dd372 TT |
237 | } |
238 | else | |
239 | { | |
240 | daemon_flag = false; | |
241 | priority = NORM_PRIORITY; | |
242 | } | |
243 | ||
244 | initialize_native (); | |
245 | } | |
246 | ||
247 | public Thread () | |
248 | { | |
249 | this (null, null, gen_name ()); | |
250 | } | |
251 | ||
252 | public Thread (Runnable r) | |
253 | { | |
254 | this (null, r, gen_name ()); | |
255 | } | |
256 | ||
257 | public Thread (String n) | |
258 | { | |
259 | this (null, null, n); | |
260 | } | |
261 | ||
262 | public Thread (ThreadGroup g, Runnable r) | |
263 | { | |
264 | this (g, r, gen_name ()); | |
265 | } | |
266 | ||
267 | public Thread (ThreadGroup g, String n) | |
268 | { | |
269 | this (g, null, n); | |
270 | } | |
271 | ||
272 | public Thread (Runnable r, String n) | |
273 | { | |
274 | this (null, r, n); | |
275 | } | |
276 | ||
277 | public String toString () | |
278 | { | |
b834f1fa BM |
279 | return "Thread[" + name + "," + priority + "," + |
280 | (group == null ? "" : group.getName()) + "]"; | |
ee9dd372 TT |
281 | } |
282 | ||
283 | public static native void yield (); | |
284 | ||
285 | // Private data. | |
286 | private ThreadGroup group; | |
287 | private String name; | |
288 | private Runnable runnable; | |
289 | private int priority; | |
290 | private boolean daemon_flag; | |
291 | private boolean interrupt_flag; | |
292 | private boolean alive_flag; | |
b834f1fa | 293 | private boolean startable_flag; |
ee9dd372 | 294 | |
aaf0766e | 295 | // Our native data. |
fc5b2138 | 296 | private Object data; |
ee9dd372 TT |
297 | |
298 | // Next thread number to assign. | |
299 | private static int nextThreadNumber = 0; | |
300 | } |