home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-05-03 | 13.0 KB | 487 lines |
- /*
- * @(#)ThreadGroup.java 1.23 96/03/25
- *
- * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for NON-COMMERCIAL purposes and without
- * fee is hereby granted provided that this copyright notice
- * appears in all copies. Please refer to the file "copyright.html"
- * for further important copyright and licensing information.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
- * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
- */
-
- package java.lang;
-
- import java.io.PrintStream;
-
- /**
- * A group of Threads. A Thread group can contain a set of Threads
- * as well as a set of other Thread groups. A Thread can access its
- * Thread group, but it can't access the parent of its Thread group.
- * This makes it possible to encapsulate a Thread in a Thread group
- * and stop it from manipulating Threads in the parent group.
- *
- * @version 1.23, 25 Mar 1996
- * @author Arthur van Hoff
- */
- public
- class ThreadGroup {
- ThreadGroup parent;
- String name;
- int maxPriority;
- boolean destroyed;
- boolean daemon;
-
- int nthreads;
- Thread threads[];
-
- int ngroups;
- ThreadGroup groups[];
-
- /**
- * Creates an empty Thread group that is not in any Thread group.
- * This method is used to create the system Thread group.
- */
- private ThreadGroup() { // called from C code
- this.name = "system";
- this.maxPriority = Thread.MAX_PRIORITY;
- }
-
- /**
- * Creates a new ThreadGroup. Its parent will be the Thread group
- * of the current Thread.
- * @param name the name of the new Thread group created
- */
- public ThreadGroup(String name) {
- this(Thread.currentThread().getThreadGroup(), name);
- }
-
- /**
- * Creates a new ThreadGroup with a specified name in the specified Thread group.
- * @param parent the specified parent Thread group
- * @param name the name of the new Thread group being created
- * @exception NullPointerException If the given thread group is equal to null.
- */
- public ThreadGroup(ThreadGroup parent, String name) {
- if (parent == null) {
- throw new NullPointerException();
- }
- parent.checkAccess();
- this.name = name;
- this.maxPriority = parent.maxPriority;
- this.daemon = parent.daemon;
- this.parent = parent;
- parent.add(this);
- }
-
- /**
- * Gets the name of this Thread group.
- */
- public final String getName() {
- return name;
- }
-
- /**
- * Gets the parent of this Thread group.
- */
- public final ThreadGroup getParent() {
- return parent;
- }
-
- /**
- * Gets the maximum priority of the group. Threads that are
- * part of this group cannot have a higher priority than the maximum priority.
- */
- public final int getMaxPriority() {
- return maxPriority;
- }
-
- /**
- * Returns the daemon flag of the Thread group. A daemon Thread group
- * is automatically destroyed when it is found empty after a Thread
- * group or Thread is removed from it.
- */
- public final boolean isDaemon() {
- return daemon;
- }
-
- /**
- * Changes the daemon status of this group.
- * @param daemon the daemon boolean which is to be set.
- */
- public final void setDaemon(boolean daemon) {
- checkAccess();
- this.daemon = daemon;
- }
-
- /**
- * Sets the maximum priority of the group. Threads
- * that are already in the group <b>can</b> have a higher priority than the
- * set maximum.
- * @param pri the priority of the Thread group
- */
- public final synchronized void setMaxPriority(int pri) {
- checkAccess();
- if (pri < Thread.MIN_PRIORITY) {
- maxPriority = Thread.MIN_PRIORITY;
- } else if (pri < maxPriority) {
- maxPriority = pri;
- }
- for (int i = 0 ; i < ngroups ; i++) {
- groups[i].setMaxPriority(pri);
- }
- }
-
- /**
- * Checks to see if this Thread group is a parent of or is equal to
- * another Thread group.
- * @param g the Thread group to be checked
- * @return true if this Thread group is equal to or is the parent of another Thread
- * group; false otherwise.
- */
- public final boolean parentOf(ThreadGroup g) {
- for (; g != null ; g = g.parent) {
- if (g == this) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Checks to see if the current Thread is allowed to modify this group.
- * @exception SecurityException If the current Thread is not allowed
- * to access this Thread group.
- */
- public final void checkAccess() {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkAccess(this);
- }
- }
-
- /**
- * Returns an estimate of the number of active Threads in the
- * Thread group.
- */
- public synchronized int activeCount() {
- if (destroyed) {
- return 0;
- }
- int n = nthreads;
- for (int i = 0 ; i < ngroups ; i++) {
- n += groups[i].activeCount();
- }
- return n;
- }
-
- /**
- * Copies, into the specified array, references to every active Thread in this Thread group.
- * You can use the activeCount() method to get an estimate of how big
- * the array should be.
- * @param list an array of Threads
- * @return the number of Threads put into the array
- */
- public int enumerate(Thread list[]) {
- return enumerate(list, 0, true);
- }
-
- /**
- * Copies, into the specified array, references to every active Thread in this Thread group.
- * You can use the activeCount() method to get an estimate of how big
- * the array should be.
- * @param list an array list of Threads
- * @param recurse a boolean indicating whether a Thread has reapearred
- * @return the number of Threads placed into the array.
- */
- public int enumerate(Thread list[], boolean recurse) {
- return enumerate(list, 0, recurse);
- }
-
- private synchronized int enumerate(Thread list[], int n, boolean recurse) {
- if (destroyed) {
- return 0;
- }
- int nt = nthreads;
- if (nt > list.length - n) {
- nt = list.length - n;
- }
- if (nt > 0) {
- System.arraycopy(threads, 0, list, n, nt);
- n += nt;
- }
- if (recurse) {
- for (int i = 0 ; i < ngroups ; i++) {
- n = groups[i].enumerate(list, n, true);
- }
- }
- return n;
- }
-
- /**
- * Returns an estimate of the number of active groups in the
- * Thread group.
- */
- public synchronized int activeGroupCount() {
- if (destroyed) {
- return 0;
- }
- int n = ngroups;
- for (int i = 0 ; i < ngroups ; i++) {
- n += groups[i].activeGroupCount();
- }
- return n;
- }
-
- /**
- * Copies, into the specified array, references to every active Thread group in this Thread
- * group. You can use the activeGroupCount() method to get an estimate of how big
- * the array should be.
- * @param list an array of Thread groups
- * @return the number of Thread groups placed into the array.
- */
- public int enumerate(ThreadGroup list[]) {
- return enumerate(list, 0, true);
- }
-
- /**
- * Copies, into the specified array, references to every active Thread group in this Thread
- * group. You can use the activeGroupCount() method to get an estimate of how big
- * the array should be.
- * @param list an array list of Thread groups
- * @param recurse a boolean indicating if a Thread group has reappeared
- * @return the number of Thread groups placed into the array.
- */
- public int enumerate(ThreadGroup list[], boolean recurse) {
- return enumerate(list, 0, recurse);
- }
-
- private synchronized int enumerate(ThreadGroup list[], int n, boolean recurse) {
- if (destroyed) {
- return 0;
- }
- int ng = ngroups;
- if (ng > list.length - n) {
- ng = list.length - n;
- }
- if (ng > 0) {
- System.arraycopy(groups, 0, list, n, ng);
- n += ng;
- }
- if (recurse) {
- for (int i = 0 ; i < ngroups ; i++) {
- n = groups[i].enumerate(list, n, true);
- }
- }
- return n;
- }
-
- /**
- * Stops all the Threads in this Thread group and all of its sub groups.
- */
- public final synchronized void stop() {
- checkAccess();
- for (int i = 0 ; i < ngroups ; i++) {
- groups[i].stop();
- }
- for (int i = 0 ; i < nthreads ; i++) {
- threads[i].stop();
- }
- }
-
- /**
- * Suspends all the Threads in this Thread group and all of its sub groups.
- */
- public final synchronized void suspend() {
- checkAccess();
- for (int i = 0 ; i < ngroups ; i++) {
- groups[i].suspend();
- }
- for (int i = 0 ; i < nthreads ; i++) {
- threads[i].suspend();
- }
- }
-
- /**
- * Resumes all the Threads in this Thread group and all of its sub groups.
- */
- public final synchronized void resume() {
- checkAccess();
- for (int i = 0 ; i < ngroups ; i++) {
- groups[i].resume();
- }
- for (int i = 0 ; i < nthreads ; i++) {
- threads[i].resume();
- }
- }
-
- /**
- * Destroys a Thread group. This does <b>NOT</b> stop the Threads
- * in the Thread group.
- * @exception IllegalThreadStateException If the Thread group is not empty
- * or if the Thread group was already destroyed.
- */
- public final synchronized void destroy() {
- checkAccess();
- if (destroyed || (nthreads > 0)) {
- throw new IllegalThreadStateException();
- }
- while (ngroups > 0) {
- groups[0].destroy();
- }
- if (parent != null) {
- destroyed = true;
- groups = null;
- threads = null;
- parent.remove(this);
- }
- }
-
- /**
- * Adds the specified Thread group to this group.
- * @param g the specified Thread group to be added
- * @exception IllegalThreadStateException If the Thread group has been destroyed.
- */
- private final synchronized void add(ThreadGroup g){
- if (destroyed) {
- throw new IllegalThreadStateException();
- }
- if (groups == null) {
- groups = new ThreadGroup[4];
- } else if (ngroups == groups.length) {
- ThreadGroup newgroups[] = new ThreadGroup[ngroups * 2];
- System.arraycopy(groups, 0, newgroups, 0, ngroups);
- groups = newgroups;
- }
- groups[ngroups] = g;
-
- // This is done last so it doesn't matter in case the
- // thread is killed
- ngroups++;
- }
-
- /**
- * Removes the specified Thread group from this group.
- * @param g the Thread group to be removed
- * @return if this Thread has already been destroyed.
- */
- private synchronized void remove(ThreadGroup g) {
- if (destroyed) {
- return;
- }
- for (int i = 0 ; i < ngroups ; i++) {
- if (groups[i] == g) {
- System.arraycopy(groups, i + 1, groups, i, --ngroups - i);
- // Zap dangling reference to the dead group so that
- // the garbage collector will collect it.
- groups[ngroups] = null;
- break;
- }
- }
- if (nthreads == 0) {
- notifyAll();
- }
- if (daemon && (nthreads == 0) && (ngroups == 0)) {
- destroy();
- }
- }
-
- /**
- * Adds the specified Thread to this group.
- * @param t the Thread to be added
- * @exception IllegalThreadStateException If the Thread group has been destroyed.
- */
- synchronized void add(Thread t) {
- if (destroyed) {
- throw new IllegalThreadStateException();
- }
- if (threads == null) {
- threads = new Thread[4];
- } else if (nthreads == threads.length) {
- Thread newthreads[] = new Thread[nthreads * 2];
- System.arraycopy(threads, 0, newthreads, 0, nthreads);
- threads = newthreads;
- }
- threads[nthreads] = t;
-
- // This is done last so it doesn't matter in case the
- // thread is killed
- nthreads++;
- }
-
- /**
- * Removes the specified Thread from this group.
- * @param t the Thread to be removed
- * @return if the Thread has already been destroyed.
- */
- synchronized void remove(Thread t) {
- if (destroyed) {
- return;
- }
- for (int i = 0 ; i < nthreads ; i++) {
- if (threads[i] == t) {
- System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
- // Zap dangling reference to the dead thread so that
- // the garbage collector will collect it.
- threads[nthreads] = null;
- break;
- }
- }
- if (nthreads == 0) {
- notifyAll();
- }
- if (daemon && (nthreads == 0) && (ngroups == 0)) {
- destroy();
- }
- }
-
- /**
- * Lists this Thread group. Useful for debugging only.
- */
- public synchronized void list() {
- list(System.out, 0);
- }
- void list(PrintStream out, int indent) {
- for (int j = 0 ; j < indent ; j++) {
- out.print(" ");
- }
- out.println(this);
- indent += 4;
- for (int i = 0 ; i < nthreads ; i++) {
- for (int j = 0 ; j < indent ; j++) {
- out.print(" ");
- }
- out.println(threads[i]);
- }
- for (int i = 0 ; i < ngroups ; i++) {
- groups[i].list(out, indent);
- }
- }
-
- /**
- * Called when a thread in this group exists because of
- * an uncaught exception.
- */
- public void uncaughtException(Thread t, Throwable e) {
- if (parent != null) {
- parent.uncaughtException(t, e);
- } else if (!(e instanceof ThreadDeath)) {
- e.printStackTrace(System.err);
- }
- }
-
- /**
- * Returns a String representation of the Thread group.
- */
- public String toString() {
- return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
- }
- }
-