| // Thread.java - Thread class. |
| |
| /* Copyright (C) 1998, 1999 Cygnus Solutions |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| package java.lang; |
| |
| /** |
| * @author Tom Tromey <tromey@cygnus.com> |
| * @date August 24, 1998 |
| */ |
| |
| /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 |
| * "The Java Language Specification", ISBN 0-201-63451-1 |
| * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. |
| * Status: Complete to version 1.1, with caveats |
| * Known problems: |
| * No attempt was made to implement suspend/resume |
| * (this could be done in some cases) |
| * Various methods which assume a VM are likewise unimplemented |
| * We do implement stop() even though it is deprecated. |
| */ |
| |
| public class Thread implements Runnable |
| { |
| public final static int MAX_PRIORITY = 10; |
| public final static int MIN_PRIORITY = 1; |
| public final static int NORM_PRIORITY = 5; |
| |
| public static int activeCount () |
| { |
| return currentThread().getThreadGroup().activeCount(); |
| } |
| |
| public void checkAccess () |
| { |
| SecurityManager s = System.getSecurityManager(); |
| if (s != null) |
| s.checkAccess(this); |
| } |
| |
| public native int countStackFrames (); |
| public static native Thread currentThread (); |
| public native void destroy (); |
| public static native void dumpStack (); |
| |
| public static int enumerate (Thread[] threads) |
| { |
| return currentThread().group.enumerate(threads); |
| } |
| |
| public final String getName () |
| { |
| return name; |
| } |
| |
| public final int getPriority () |
| { |
| return priority; |
| } |
| |
| public final ThreadGroup getThreadGroup () |
| { |
| return group; |
| } |
| |
| public native void interrupt (); |
| |
| public static boolean interrupted () |
| { |
| return currentThread().isInterrupted(); |
| } |
| |
| // FIXME: it seems to me that this should be synchronized. |
| public boolean isInterrupted () |
| { |
| boolean r = interrupt_flag; |
| interrupt_flag = false; |
| return r; |
| } |
| |
| public final boolean isAlive () |
| { |
| return alive_flag; |
| } |
| |
| public final boolean isDaemon () |
| { |
| return daemon_flag; |
| } |
| |
| public final void join () throws InterruptedException |
| { |
| join (0, 0); |
| } |
| |
| public final void join (long timeout) throws InterruptedException |
| { |
| join (timeout, 0); |
| } |
| |
| public final native void join (long timeout, int nanos) |
| throws InterruptedException; |
| |
| public final native void resume (); |
| |
| // This method exists only to avoid a warning from the C++ compiler. |
| private static final native void run__ (Object obj); |
| private native final void finish_ (); |
| private final void run_ () |
| { |
| try |
| { |
| run (); |
| } |
| catch (Throwable e) |
| { |
| // Uncaught exceptions are forwarded to the ThreadGroup. If |
| // this results in an uncaught exception, that is ignored. |
| try |
| { |
| group.uncaughtException(this, e); |
| } |
| catch (Throwable f) |
| { |
| // Nothing. |
| } |
| } |
| finish_ (); |
| } |
| |
| public void run () |
| { |
| if (runnable != null) |
| runnable.run(); |
| } |
| |
| public final void setDaemon (boolean status) |
| { |
| checkAccess (); |
| if (isAlive ()) |
| throw new IllegalThreadStateException (); |
| daemon_flag = status; |
| } |
| |
| // TODO12: |
| // public ClassLoader getContextClassLoader() |
| // { |
| // } |
| |
| // TODO12: |
| // public void setContextClassLoader(ClassLoader cl) |
| // { |
| // } |
| |
| public final void setName (String n) |
| { |
| checkAccess (); |
| // The Class Libraries book says ``threadName cannot be null''. I |
| // take this to mean NullPointerException. |
| if (n == null) |
| throw new NullPointerException (); |
| name = n; |
| } |
| |
| public final native void setPriority (int newPriority); |
| |
| public static void sleep (long timeout) throws InterruptedException |
| { |
| sleep (timeout, 0); |
| } |
| |
| public static native void sleep (long timeout, int nanos) |
| throws InterruptedException; |
| public synchronized native void start (); |
| |
| public final void stop () |
| { |
| stop (new ThreadDeath ()); |
| } |
| |
| public final synchronized native void stop (Throwable e); |
| public final native void suspend (); |
| |
| private final native void initialize_native (); |
| |
| private final synchronized static String gen_name () |
| { |
| String n; |
| n = "Thread-" + nextThreadNumber; |
| ++nextThreadNumber; |
| return n; |
| } |
| |
| public Thread (ThreadGroup g, Runnable r, String n) |
| { |
| // Note that CURRENT can be null when we are creating the very |
| // first thread. That's why we check it below. |
| Thread current = currentThread (); |
| |
| if (g != null) |
| { |
| // If CURRENT is null, then we are creating the first thread. |
| // In this case we don't do the security check. |
| if (current != null) |
| g.checkAccess(); |
| } |
| else |
| g = current.getThreadGroup(); |
| |
| // The Class Libraries book says ``threadName cannot be null''. I |
| // take this to mean NullPointerException. |
| if (n == null) |
| throw new NullPointerException (); |
| |
| name = n; |
| group = g; |
| g.add(this); |
| runnable = r; |
| |
| data = null; |
| interrupt_flag = false; |
| alive_flag = false; |
| if (current != null) |
| { |
| daemon_flag = current.isDaemon(); |
| priority = current.getPriority(); |
| } |
| else |
| { |
| daemon_flag = false; |
| priority = NORM_PRIORITY; |
| } |
| |
| initialize_native (); |
| } |
| |
| public Thread () |
| { |
| this (null, null, gen_name ()); |
| } |
| |
| public Thread (Runnable r) |
| { |
| this (null, r, gen_name ()); |
| } |
| |
| public Thread (String n) |
| { |
| this (null, null, n); |
| } |
| |
| public Thread (ThreadGroup g, Runnable r) |
| { |
| this (g, r, gen_name ()); |
| } |
| |
| public Thread (ThreadGroup g, String n) |
| { |
| this (g, null, n); |
| } |
| |
| public Thread (Runnable r, String n) |
| { |
| this (null, r, n); |
| } |
| |
| public String toString () |
| { |
| return "Thread[" + name + "," + priority + "," + group.getName() + "]"; |
| } |
| |
| public static native void yield (); |
| |
| // Private data. |
| private ThreadGroup group; |
| private String name; |
| private Runnable runnable; |
| private int priority; |
| private boolean daemon_flag; |
| private boolean interrupt_flag; |
| private boolean alive_flag; |
| |
| // This is a bit odd. We need a way to represent some data that is |
| // manipulated only by the native side of this class. We represent |
| // it as a Java object reference. However, it is not actually a |
| // Java object. |
| private Object data; |
| |
| // Next thread number to assign. |
| private static int nextThreadNumber = 0; |
| } |