mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			617 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			617 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* java.lang.ThreadGroup
 | |
|    Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
|  
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | |
| 02111-1307 USA.
 | |
| 
 | |
| As a special exception, if you link this library with other files to
 | |
| produce an executable, this library does not by itself cause the
 | |
| resulting executable to be covered by the GNU General Public License.
 | |
| This exception does not however invalidate any other reasons why the
 | |
| executable file might be covered by the GNU General Public License. */
 | |
|  
 | |
| package java.lang;
 | |
| 
 | |
| import java.util.Vector;
 | |
| import java.util.Enumeration;
 | |
| 
 | |
| /* 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 from http://www.javasoft.com.
 | |
|  * Status:  Complete for 1.2.  Some parts from the JDK 1.0 spec only are
 | |
|  * not implemented. 
 | |
|  */
 | |
|  
 | |
| /**
 | |
|  * ThreadGroup allows you to group Threads together.  There is a
 | |
|  * hierarchy of ThreadGroups, and only the initial ThreadGroup has
 | |
|  * no parent.  A Thread may access information about its own
 | |
|  * ThreadGroup, but not its parents or others outside the tree.
 | |
|  *
 | |
|  * @author John Keiser
 | |
|  * @author Tom Tromey
 | |
|  * @author Bryce McKinlay
 | |
|  * @version 1.2.0
 | |
|  * @since JDK1.0
 | |
|  */
 | |
| 
 | |
| public class ThreadGroup
 | |
| {
 | |
|   /* The Initial, top-level ThreadGroup. */
 | |
|   static ThreadGroup root = new ThreadGroup();
 | |
|   /* This flag is set if an uncaught exception occurs. The runtime should 
 | |
|   check this and exit with an error status if it is set. */
 | |
|   static boolean had_uncaught_exception = false;
 | |
| 
 | |
|   private ThreadGroup parent;
 | |
|   private String name;
 | |
|   private Vector threads = new Vector();
 | |
|   private Vector groups = new Vector();
 | |
|   private boolean daemon_flag = false;
 | |
|   private int maxpri = Thread.MAX_PRIORITY;
 | |
| 
 | |
|   private ThreadGroup()
 | |
|   {
 | |
|     name = "main";    
 | |
|   }
 | |
| 
 | |
|   /** Create a new ThreadGroup using the given name and the
 | |
|    *  current thread's ThreadGroup as a parent.
 | |
|    *  @param name the name to use for the ThreadGroup.
 | |
|    */
 | |
|   public ThreadGroup(String name)
 | |
|   {
 | |
|     this (Thread.currentThread().getThreadGroup(), name);
 | |
|   }
 | |
| 
 | |
|   /** Create a new ThreadGroup using the given name and
 | |
|    *  parent group.
 | |
|    *  @param name the name to use for the ThreadGroup.
 | |
|    *  @param parent the ThreadGroup to use as a parent.
 | |
|    *  @exception NullPointerException if parent is null.
 | |
|    *  @exception SecurityException if you cannot change
 | |
|    *             the intended parent group.
 | |
|    */
 | |
|   public ThreadGroup(ThreadGroup parent, String name)
 | |
|   {
 | |
|     parent.checkAccess();
 | |
|     this.parent = parent;
 | |
|     if (parent.isDestroyed())
 | |
|       throw new IllegalArgumentException ();
 | |
|     this.name = name;
 | |
|     maxpri = parent.maxpri;
 | |
|     daemon_flag = parent.daemon_flag;
 | |
|     parent.addGroup(this);
 | |
|   }
 | |
| 
 | |
|   /** Get the name of this ThreadGroup.
 | |
|    *  @return the name of this ThreadGroup.
 | |
|    */
 | |
|   public final String getName()
 | |
|   {
 | |
|     return name;
 | |
|   }
 | |
| 
 | |
|   /** Get the parent of this ThreadGroup.
 | |
|    *  @return the parent of this ThreadGroup.
 | |
|    */
 | |
|   public final ThreadGroup getParent()
 | |
|   {
 | |
|     return parent;
 | |
|   }
 | |
| 
 | |
|   /** Set the maximum priority for Threads in this ThreadGroup. setMaxPriority
 | |
|    *  can only be used to reduce the current maximum. If maxpri
 | |
|    *  is greater than the current Maximum, the current value is not changed.
 | |
|    *  Calling this does not effect threads already in this ThreadGroup.
 | |
|    *  @param maxpri the new maximum priority for this ThreadGroup.
 | |
|    *  @exception SecurityException if you cannoy modify this ThreadGroup.
 | |
|    */
 | |
|   public final synchronized void setMaxPriority(int maxpri)
 | |
|   {
 | |
|     checkAccess();
 | |
|     if (maxpri < this.maxpri
 | |
|         && maxpri >= Thread.MIN_PRIORITY
 | |
| 	&& maxpri <= Thread.MAX_PRIORITY)
 | |
|       {
 | |
| 	this.maxpri = maxpri;        
 | |
|       }  
 | |
|   }
 | |
| 
 | |
|   /** Get the maximum priority of Threads in this ThreadGroup.
 | |
|    *  @return the maximum priority of Threads in this ThreadGroup.
 | |
|    */
 | |
|   public final int getMaxPriority()
 | |
|   {
 | |
|     return maxpri;
 | |
|   }
 | |
| 
 | |
|   /** Set whether this ThreadGroup is a daemon group.  A daemon
 | |
|    *  group will be destroyed when its last thread is stopped and
 | |
|    *  its last thread group is destroyed.
 | |
|    *  @specnote The Java API docs indicate that the group is destroyed
 | |
|    * 		when either of those happen, but that doesn't make
 | |
|    * 		sense.
 | |
|    *  @param daemon whether this ThreadGroup should be a daemon group.
 | |
|    *  @exception SecurityException if you cannoy modify this ThreadGroup.
 | |
|    */
 | |
|   public final void setDaemon (boolean daemon)
 | |
|   {
 | |
|     checkAccess();
 | |
|     daemon_flag = daemon;
 | |
|   }
 | |
|    
 | |
|   /** Tell whether this ThreadGroup is a daemon group.  A daemon
 | |
|     * group will be destroyed when its last thread is stopped and
 | |
|     * its last thread group is destroyed.
 | |
|     * @specnote The Java API docs indicate that the group is destroyed
 | |
|     *		when either of those happen, but that doesn't make
 | |
|     *		sense.
 | |
|     * @return whether this ThreadGroup is a daemon group.
 | |
|     */
 | |
|   public final boolean isDaemon()
 | |
|   {
 | |
|     return daemon_flag;
 | |
|   }
 | |
| 
 | |
|   /** Tell whether this ThreadGroup has been destroyed or not.
 | |
|     * @return whether this ThreadGroup has been destroyed or not.
 | |
|     */
 | |
|   public synchronized boolean isDestroyed()
 | |
|   {
 | |
|     return parent == null && this != root;
 | |
|   }
 | |
| 
 | |
|   /** Check whether this ThreadGroup is an ancestor of the
 | |
|     * specified ThreadGroup, or if they are the same.
 | |
|     *
 | |
|     * @param g the group to test on.
 | |
|     * @return whether this ThreadGroup is a parent of the
 | |
|     *	      specified group.
 | |
|     */
 | |
|   public final boolean parentOf(ThreadGroup tg)
 | |
|   {
 | |
|     while (tg != null)
 | |
|       {
 | |
|         if (tg == this)
 | |
|           return true;
 | |
|         tg = tg.parent;
 | |
|       }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /** Return the total number of active threads in this ThreadGroup
 | |
|     * and all its descendants.<P>
 | |
|     *
 | |
|     * This cannot return an exact number, since the status of threads
 | |
|     * may change after they were counted.  But it should be pretty
 | |
|     * close.<P>
 | |
|     *
 | |
|     * @return the number of active threads in this ThreadGroup and
 | |
|     *	      its descendants.
 | |
|     * @specnote it isn't clear what the definition of an "Active" thread is.
 | |
|     *           Current JDKs regard a thread as active if has been
 | |
|     *           started and not finished.  We implement this behaviour.
 | |
|     *           There is a JDC bug, <A HREF="http://developer.java.sun.com/developer/bugParade/bugs/4089701.html">
 | |
|     *           4089701</A>, regarding this issue.
 | |
|     *           
 | |
|     */
 | |
|   public synchronized int activeCount()
 | |
|   {
 | |
|     int total = 0;
 | |
|     for (int i = 0; i < threads.size(); ++i)
 | |
|       {
 | |
| 	if (((Thread) threads.elementAt(i)).isAlive ())
 | |
| 	  ++total;
 | |
|       }
 | |
| 
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup g = (ThreadGroup) groups.elementAt(i);
 | |
|         total += g.activeCount();
 | |
|       }
 | |
|     return total;
 | |
|   }
 | |
| 
 | |
|   /** Get the number of active groups in this ThreadGroup.  This group
 | |
|     * itself is not included in the count.
 | |
|     * @specnote it is unclear what exactly constitutes an
 | |
|     *		active ThreadGroup.  Currently we assume that
 | |
|     *		all sub-groups are active, per current JDKs.
 | |
|     * @return the number of active groups in this ThreadGroup.
 | |
|     */
 | |
|   public synchronized int activeGroupCount()
 | |
|   {
 | |
|     int total = groups.size();
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
| 	ThreadGroup g = (ThreadGroup) groups.elementAt(i);
 | |
| 	total += g.activeGroupCount();
 | |
|       }
 | |
|     return total;
 | |
|   }
 | |
| 
 | |
|   /** Copy all of the active Threads from this ThreadGroup and
 | |
|     * its descendants into the specified array.  If the array is
 | |
|     * not big enough to hold all the Threads, extra Threads will
 | |
|     * simply not be copied.
 | |
|     *
 | |
|     * @param threads the array to put the threads into.
 | |
|     * @return the number of threads put into the array.
 | |
|     */
 | |
|   public int enumerate(Thread[] threads)
 | |
|   {
 | |
|     return enumerate(threads, 0, true);
 | |
|   }
 | |
| 
 | |
|   /** Copy all of the active Threads from this ThreadGroup and,
 | |
|     * if desired, from its descendants, into the specified array.
 | |
|     * If the array is not big enough to hold all the Threads,
 | |
|     * extra Threads will simply not be copied.
 | |
|     *
 | |
|     * @param threads the array to put the threads into.
 | |
|     * @param useDescendants whether to count Threads in this
 | |
|     *	     ThreadGroup's descendants or not.
 | |
|     * @return the number of threads put into the array.
 | |
|     */
 | |
|   public int enumerate(Thread[] threads, boolean useDescendants)
 | |
|   {
 | |
|     return enumerate(threads, 0, useDescendants);
 | |
|   }
 | |
| 
 | |
|   // This actually implements enumerate.
 | |
|   private synchronized int enumerate(Thread[] list, int next_index, 
 | |
| 				     boolean recurse)
 | |
|   {
 | |
|     Enumeration e = threads.elements();
 | |
|     while (e.hasMoreElements() && next_index < list.length)
 | |
|       {
 | |
| 	Thread t = (Thread) e.nextElement();
 | |
| 	if (t.isAlive ())
 | |
| 	  list[next_index++] = t;
 | |
|       }
 | |
|     if (recurse && next_index != list.length)
 | |
|       {
 | |
| 	e = groups.elements();
 | |
| 	while (e.hasMoreElements() && next_index < list.length)
 | |
| 	  {
 | |
| 	    ThreadGroup g = (ThreadGroup) e.nextElement();
 | |
| 	    next_index = g.enumerate(list, next_index, true);
 | |
| 	  }
 | |
|       }
 | |
|     return next_index;
 | |
|   }
 | |
| 
 | |
|   /** Copy all active ThreadGroups that are descendants of this
 | |
|     * ThreadGroup into the specified array.  If the array is not
 | |
|     * large enough to hold all active ThreadGroups, extra
 | |
|     * ThreadGroups simply will not be copied.
 | |
|     *
 | |
|     * @param groups the array to put the ThreadGroups into.
 | |
|     * @return the number of ThreadGroups copied into the array.
 | |
|     */
 | |
|   public int enumerate(ThreadGroup[] groups)
 | |
|   {
 | |
|     return enumerate(groups, 0, true);
 | |
|   }
 | |
| 
 | |
|   /** Copy all active ThreadGroups that are children of this
 | |
|     * ThreadGroup into the specified array, and if desired, also
 | |
|     * copy all active descendants into the array.  If the array
 | |
|     * is not large enough to hold all active ThreadGroups, extra
 | |
|     * ThreadGroups simply will not be copied.
 | |
|     *
 | |
|     * @param groups the array to put the ThreadGroups into.
 | |
|     * @param recurse whether to include all descendants
 | |
|     *	     of this ThreadGroup's children in determining
 | |
|     *	     activeness.
 | |
|     * @return the number of ThreadGroups copied into the array.
 | |
|     */
 | |
|   public int enumerate(ThreadGroup[] groups, boolean recurse)
 | |
|   {
 | |
|     return enumerate(groups, 0, recurse);
 | |
|   }
 | |
| 
 | |
|   // This actually implements enumerate.
 | |
|   private synchronized int enumerate (ThreadGroup[] list, int next_index, 
 | |
| 				      boolean recurse)
 | |
|   {
 | |
|     Enumeration e = groups.elements();
 | |
|     while (e.hasMoreElements() && next_index < list.length)
 | |
|       {
 | |
| 	ThreadGroup g = (ThreadGroup) e.nextElement();
 | |
| 	list[next_index++] = g;
 | |
| 	if (recurse && next_index != list.length)
 | |
| 	  next_index = g.enumerate(list, next_index, true);
 | |
|       }
 | |
|     return next_index;
 | |
|   }
 | |
| 
 | |
|   /** Interrupt all Threads in this ThreadGroup and its sub-groups.
 | |
|     * @exception SecurityException if you cannot modify this
 | |
|     *		 ThreadGroup or any of its Threads or children
 | |
|     *		 ThreadGroups.
 | |
|     * @since JDK1.2
 | |
|     */
 | |
|   public final synchronized void interrupt()
 | |
|   {
 | |
|     checkAccess();
 | |
|     for (int i=0; i < threads.size(); i++)
 | |
|       {
 | |
|         Thread t = (Thread) threads.elementAt(i);
 | |
|         t.interrupt();
 | |
|       }
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
|         tg.interrupt();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** Stop all Threads in this ThreadGroup and its descendants.
 | |
|     * @exception SecurityException if you cannot modify this
 | |
|     *		 ThreadGroup or any of its Threads or children
 | |
|     *		 ThreadGroups.
 | |
|     * @deprecated This method calls Thread.stop(), which is dangerous.
 | |
|     */
 | |
|   public final synchronized void stop()
 | |
|   {
 | |
|     checkAccess();
 | |
|     for (int i=0; i<threads.size(); i++)
 | |
|       {
 | |
|         Thread t = (Thread) threads.elementAt(i);
 | |
| 	t.stop();
 | |
|       }
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
|         tg.stop();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** Suspend all Threads in this ThreadGroup and its descendants.
 | |
|     * @exception SecurityException if you cannot modify this
 | |
|     *		 ThreadGroup or any of its Threads or children
 | |
|     *		 ThreadGroups.
 | |
|     * @deprecated This method calls Thread.suspend(), which is dangerous.
 | |
|     */
 | |
|   public final synchronized void suspend()
 | |
|   {
 | |
|     checkAccess();
 | |
|     for (int i=0; i<threads.size(); i++)
 | |
|       {
 | |
|         Thread t = (Thread) threads.elementAt(i);
 | |
|         t.suspend();
 | |
|       }
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
|         tg.suspend();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** Resume all Threads in this ThreadGroup and its descendants.
 | |
|     * @exception SecurityException if you cannot modify this
 | |
|     *		 ThreadGroup or any of its Threads or children
 | |
|     *		 ThreadGroups.
 | |
|     * @deprecated This method relies on Thread.suspend(), which is dangerous.
 | |
|     */
 | |
|   public final synchronized void resume()
 | |
|   {
 | |
|     checkAccess();
 | |
|     for (int i=0; i < threads.size(); i++)
 | |
|       {
 | |
|         Thread t = (Thread) threads.elementAt(i);
 | |
| 	t.resume();
 | |
|       }
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
|         tg.resume();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // This is a helper that is used to implement the destroy method.
 | |
|   private synchronized void checkDestroy ()
 | |
|   {
 | |
|     if (! threads.isEmpty())
 | |
|       throw new IllegalThreadStateException ("ThreadGroup has threads");
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
| 	tg.checkDestroy();
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** Destroy this ThreadGroup.  There can be no Threads in it,
 | |
|     * and none of its descendants (sub-groups) may have Threads in them.
 | |
|     * All its descendants will be destroyed as well.
 | |
|     * @exception IllegalThreadStateException if the ThreadGroup or
 | |
|     *		 its descendants have Threads remaining in them, or
 | |
|     *		 if the ThreadGroup in question is already destroyed.
 | |
|     * @exception SecurityException if you cannot modify this
 | |
|     *		 ThreadGroup or any of its descendants.
 | |
|     */
 | |
|   public final synchronized void destroy()
 | |
|   {
 | |
|     checkAccess();
 | |
|     if (isDestroyed())
 | |
|       throw new IllegalThreadStateException("Already destroyed.");
 | |
|     checkDestroy ();
 | |
|     if (parent != null)
 | |
|       parent.removeGroup(this);
 | |
|     parent = null;
 | |
| 
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
| 	tg.destroy();
 | |
|       }
 | |
|   }
 | |
|   
 | |
|   /** Print out information about this ThreadGroup to System.out.
 | |
|     */
 | |
|   public void list()
 | |
|   {
 | |
|     list("");
 | |
|   }
 | |
| 
 | |
|   private synchronized void list(String indentation)
 | |
|   {
 | |
|     System.out.print(indentation);
 | |
|     System.out.println(toString ());
 | |
|     String sub = indentation + "    ";
 | |
|     for (int i=0; i < threads.size(); i++)
 | |
|       {
 | |
|         Thread t = (Thread) threads.elementAt(i);
 | |
| 	System.out.print(sub);
 | |
| 	System.out.println(t.toString());
 | |
|       }
 | |
|     for (int i=0; i < groups.size(); i++)
 | |
|       {
 | |
|         ThreadGroup tg = (ThreadGroup) groups.elementAt(i);
 | |
| 	tg.list(sub);
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** When a Thread in this ThreadGroup does not catch an exception,
 | |
|     * this method of the ThreadGroup is called.<P>
 | |
|     *
 | |
|     * ThreadGroup's implementation does the following:<BR>
 | |
|     * <OL>
 | |
|     * <LI>If there is a parent ThreadGroup, call uncaughtException()
 | |
|     *	  in the parent.</LI>
 | |
|     * <LI>If the Throwable passed is a ThreadDeath, don't do
 | |
|     *	  anything.</LI>
 | |
|     * <LI>Otherwise, call <CODE>exception.printStackTrace().</CODE></LI>
 | |
|     * </OL>
 | |
|     *
 | |
|     * @param thread the thread that exited.
 | |
|     * @param exception the uncaught exception.
 | |
|     */
 | |
|   public void uncaughtException(Thread thread, Throwable t)
 | |
|   {
 | |
|     if (parent != null)
 | |
|       parent.uncaughtException (thread, t);
 | |
|     else if (! (t instanceof ThreadDeath))
 | |
|       {
 | |
|         if (thread != null)
 | |
|           System.err.print ("Exception in thread \""
 | |
| 			    + thread.getName() + "\" ");
 | |
| 	try
 | |
| 	  {
 | |
| 	    t.printStackTrace(System.err);
 | |
| 	  }
 | |
| 	catch (Throwable x)
 | |
| 	  {
 | |
| 	    // This means that something is badly screwed up with the runtime,
 | |
| 	    // or perhaps someone is messing with the SecurityManager. In any
 | |
| 	    // case, try to deal with it gracefully.
 | |
| 	    System.err.println(t);
 | |
| 	    System.err.println("*** Got " + x.toString() + 
 | |
| 			       " while trying to print stack trace");
 | |
| 	  }
 | |
| 	had_uncaught_exception = true;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /** Tell the VM whether it may suspend Threads in low memory
 | |
|     * situations.
 | |
|     * @deprecated This method is unimplemented, because it would rely on
 | |
|     *		  suspend(), which is deprecated. There is no way for a Java
 | |
|     *		  program to determine whether this has any effect whatsoever,
 | |
|     *		  so we don't need it.
 | |
|     * @return false
 | |
|     */
 | |
|   public boolean allowThreadSuspension(boolean allow)
 | |
|   {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   /** Get a human-readable representation of this ThreadGroup.
 | |
|     * @return a String representing this ThreadGroup.
 | |
|     * @specnote Language Spec and Class Libraries book disagree a bit here.
 | |
|     *		We follow the Spec, but add "ThreadGroup" per the book.  We
 | |
|     *		include "java.lang" based on the list() example in the Class
 | |
|     *		Libraries book.
 | |
|     */
 | |
|   public String toString ()
 | |
|   {
 | |
|     return "java.lang.ThreadGroup[name=" + name + 
 | |
|            ",maxpri=" + maxpri + "]";
 | |
|   }
 | |
| 
 | |
|   /** Find out if the current Thread can modify this ThreadGroup.
 | |
|     * Calls the current SecurityManager's checkAccess() method to
 | |
|     * find out.  If there is none, it assumes everything's OK.
 | |
|     * @exception SecurityException if the current Thread cannot
 | |
|     *		 modify this ThreadGroup.
 | |
|     */
 | |
|   public final void checkAccess()
 | |
|   {
 | |
|     SecurityManager sm = System.getSecurityManager();
 | |
|     if (sm != null)
 | |
|       sm.checkAccess(this);
 | |
|   }
 | |
| 
 | |
|   // This is called to add a Thread to our internal list.
 | |
|   final synchronized void addThread(Thread t)
 | |
|   {
 | |
|     if (isDestroyed())
 | |
|       throw new IllegalThreadStateException ("ThreadGroup is destroyed");
 | |
|   
 | |
|     threads.addElement(t);
 | |
|   }
 | |
| 
 | |
|   // This is called to remove a Thread from our internal list.
 | |
|   final synchronized void removeThread(Thread t)
 | |
|   {
 | |
|     if (isDestroyed())
 | |
|       throw new IllegalThreadStateException ();
 | |
|   
 | |
|     threads.removeElement(t);
 | |
|     // Daemon groups are automatically destroyed when all their threads die.
 | |
|     if (daemon_flag && groups.size() == 0 && threads.size() == 0)
 | |
|       {
 | |
| 	// We inline destroy to avoid the access check.
 | |
| 	if (parent != null)
 | |
| 	  parent.removeGroup(this);
 | |
| 	parent = null;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   // This is called to add a ThreadGroup to our internal list.
 | |
|   final synchronized void addGroup(ThreadGroup g)
 | |
|   {
 | |
|     groups.addElement(g);
 | |
|   }
 | |
| 
 | |
|   // This is called to remove a ThreadGroup from our internal list.
 | |
|   final synchronized void removeGroup(ThreadGroup g)
 | |
|   {
 | |
|     groups.removeElement(g);
 | |
|     // Daemon groups are automatically destroyed when all their threads die.
 | |
|     if (daemon_flag && groups.size() == 0 && threads.size() == 0)
 | |
|       {
 | |
| 	// We inline destroy to avoid the access check.
 | |
| 	if (parent != null)
 | |
| 	  parent.removeGroup(this);
 | |
| 	parent = null;
 | |
|       }
 | |
|   }
 | |
| }
 |