home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / solaris2 / jdk / src / java / lang / threadgr.jav < prev    next >
Encoding:
Text File  |  1995-10-30  |  12.6 KB  |  463 lines

  1. /*
  2.  * @(#)ThreadGroup.java    1.18 95/10/21  
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package java.lang;
  21.  
  22. import java.io.PrintStream;
  23.  
  24. /**
  25.  * A group of Threads. A Thread group can contain a set of Threads
  26.  * as well as a set of other Thread groups. A Thread can access its
  27.  * Thread group, but it can't access the parent of its Thread group.
  28.  * This makes it possible to encapsulate a Thread in a Thread group
  29.  * and stop it from manipulating Threads in the parent group.
  30.  *
  31.  * @version     1.18, 10/21/95
  32.  * @author    Arthur van Hoff
  33.  */
  34. public
  35. class ThreadGroup {
  36.     ThreadGroup parent;
  37.     String name;
  38.     int maxPriority;
  39.     boolean destroyed;
  40.     boolean daemon;
  41.  
  42.     int nthreads;
  43.     Thread threads[];
  44.  
  45.     int ngroups;
  46.     ThreadGroup groups[];
  47.  
  48.     /**
  49.      * Creates an empty Thread group that is not in any Thread group. 
  50.      * This method is used to create the system Thread group.
  51.      */
  52.     private ThreadGroup() {    // called from C code
  53.     this.name = "system";
  54.     this.maxPriority = Thread.MAX_PRIORITY;
  55.     }
  56.  
  57.     /**
  58.      * Creates a new ThreadGroup. Its parent will be the Thread group
  59.      * of the current Thread.
  60.      * @param name the name of the new Thread group created
  61.      */
  62.     public ThreadGroup(String name) {
  63.     this(Thread.currentThread().getThreadGroup(), name);
  64.     }
  65.  
  66.     /**
  67.      * Creates a new ThreadGroup with a specified name in the specified Thread group.
  68.      * @param parent the specified parent Thread group
  69.      * @param name the name of the new Thread group being created
  70.      * @exception NullPointerException If the given thread group is equal to null.
  71.      */
  72.     public ThreadGroup(ThreadGroup parent, String name) {
  73.     if (parent == null) {
  74.         throw new NullPointerException();
  75.     }
  76.     parent.checkAccess();
  77.     this.name = name;
  78.     this.maxPriority = parent.maxPriority;
  79.     this.daemon = parent.daemon;
  80.     this.parent = parent;
  81.     parent.add(this);
  82.     }
  83.  
  84.     /**
  85.      * Gets the name of this Thread group.
  86.      */
  87.     public final String getName() {
  88.     return name;
  89.     }
  90.  
  91.     /**
  92.      * Gets the parent of this Thread group.
  93.      */
  94.     public final ThreadGroup getParent() {
  95.     return parent;
  96.     }
  97.  
  98.     /**
  99.      * Gets the maximum priority of the group. Threads that are
  100.      * part of this group cannot have a higher priority than the maximum priority.
  101.      */
  102.     public final int getMaxPriority() {
  103.     return maxPriority;
  104.     }
  105.  
  106.     /**
  107.      * Returns the daemon flag of the Thread group. A daemon Thread group
  108.      * is automatically destroyed when it is found empty after a Thread
  109.      * group or Thread is removed from it.
  110.      */
  111.     public final boolean isDaemon() {
  112.     return daemon;
  113.     }
  114.  
  115.     /**
  116.      * Changes the daemon status of this group.
  117.      * @param daemon the daemon boolean which is to be set.
  118.      */
  119.     public final void setDaemon(boolean daemon) {
  120.     checkAccess();
  121.     this.daemon = daemon;
  122.     }
  123.  
  124.     /**
  125.      * Sets the maximum priority of the group. Threads
  126.      * that are already in the group <b>can</b> have a higher priority than the
  127.      * set maximum.
  128.      * @param pri the priority of the Thread group
  129.      */
  130.     public final synchronized void setMaxPriority(int pri) {
  131.     checkAccess();
  132.     if (pri < Thread.MIN_PRIORITY) {
  133.         maxPriority = Thread.MIN_PRIORITY;
  134.     } else if (pri < maxPriority) {
  135.         maxPriority = pri;
  136.     }
  137.     for (int i = 0 ; i < ngroups ; i++) {
  138.         groups[i].setMaxPriority(i);
  139.     }
  140.     }
  141.  
  142.     /**
  143.      * Checks to see if this Thread group is a parent of or is equal to
  144.      * another Thread group.
  145.      * @param g the Thread group to be checked
  146.      * @return true if this Thread group is equal to or is the parent of another Thread
  147.      * group; false otherwise.
  148.      */
  149.     public final boolean parentOf(ThreadGroup g) {
  150.     for (; g != null ; g = g.parent) {
  151.         if (g == this) {
  152.         return true;
  153.         }
  154.     }
  155.     return false;
  156.     }
  157.  
  158.     /**
  159.      * Checks to see if the current Thread is allowed to modify this group.
  160.      * @exception SecurityException If the current Thread is not allowed 
  161.      * to access this Thread group.
  162.      */
  163.     public final void checkAccess() {
  164.     SecurityManager security = System.getSecurityManager();
  165.     if (security != null) {
  166.         security.checkAccess(this);
  167.     }
  168.     }
  169.  
  170.     /**
  171.      * Returns an estimate of the number of active Threads in the
  172.      * Thread group.
  173.      */
  174.     public synchronized int activeCount() {
  175.     int n = nthreads;
  176.     for (int i = 0 ; i < ngroups ; i++) {
  177.         n += groups[i].activeCount();
  178.     }
  179.     return n;
  180.     }
  181.  
  182.     /**
  183.      * Copies, into the specified array, references to every active Thread in this Thread group.
  184.      * You can use the activeCount() method to get an estimate of how big
  185.      * the array should be.
  186.      * @param list an array of Threads
  187.      * @return the number of Threads put into the array
  188.      */
  189.     public int enumerate(Thread list[]) {
  190.     return enumerate(list, 0, true);
  191.     }
  192.  
  193.     /**
  194.      * Copies, into the specified array, references to every active Thread in this Thread group.
  195.      * You can use the activeCount() method to get an estimate of how big
  196.      * the array should be.
  197.      * @param list an array list of Threads
  198.      * @param recurse a boolean indicating whether a Thread has reapearred
  199.      * @return the number of Threads placed into the array.
  200.      */
  201.     public int enumerate(Thread list[], boolean recurse) {
  202.     return enumerate(list, 0, recurse);
  203.     }
  204.  
  205.     private synchronized int enumerate(Thread list[], int n, boolean recurse) {
  206.     int nt = nthreads;
  207.     if (nt > list.length - n) {
  208.         nt = list.length - n;
  209.     }
  210.     if (nt > 0) {
  211.         System.arraycopy(threads, 0, list, n, nt);
  212.         n += nt;
  213.     }
  214.     if (recurse) {
  215.         for (int i = 0 ; i < ngroups ; i++) {
  216.         n = groups[i].enumerate(list, n, true);
  217.         }
  218.     }
  219.     return n;
  220.     }
  221.  
  222.     /**
  223.      * Returns an estimate of the number of active groups in the
  224.      * Thread group.
  225.      */
  226.     public synchronized int activeGroupCount() {
  227.     int n = ngroups;
  228.     for (int i = 0 ; i < ngroups ; i++) {
  229.         n += groups[i].activeGroupCount();
  230.     }
  231.     return n;
  232.     }
  233.  
  234.     /**
  235.      * Copies, into the specified array, references to every active Thread group in this Thread 
  236.      * group.  You can use the activeGroupCount() method to get an estimate of how big
  237.      * the array should be.
  238.      * @param list an array of Thread groups
  239.      * @return the number of Thread groups placed into the array.
  240.      */
  241.     public int enumerate(ThreadGroup list[]) {
  242.     return enumerate(list, 0, true);
  243.     }
  244.  
  245.     /**
  246.      * Copies, into the specified array, references to every active Thread group in this Thread 
  247.      * group.  You can use the activeGroupCount() method to get an estimate of how big
  248.      * the array should be.
  249.      * @param list an array list of Thread groups
  250.      * @param recurse a boolean indicating if a Thread group has reappeared
  251.      * @return the number of Thread groups placed into the array.
  252.      */
  253.     public int enumerate(ThreadGroup list[], boolean recurse) {
  254.     return enumerate(list, 0, recurse);
  255.     }
  256.  
  257.     private synchronized int enumerate(ThreadGroup list[], int n, boolean recurse) {
  258.     int ng = ngroups;
  259.     if (ng > list.length - n) {
  260.         ng = list.length - n;
  261.     }
  262.     if (ng > 0) {
  263.         System.arraycopy(groups, 0, list, n, ng);
  264.         n += ng;
  265.     }
  266.     if (recurse) {
  267.         for (int i = 0 ; i < ngroups ; i++) {
  268.         n = groups[i].enumerate(list, n, true);
  269.         }
  270.     }
  271.     return n;
  272.     }
  273.  
  274.     /**
  275.      * Stops all the Threads in this Thread group and all of its sub groups.
  276.      */
  277.     public final synchronized void stop() {
  278.     checkAccess();
  279.     for (int i = 0 ; i < ngroups ; i++) {
  280.         groups[i].stop();
  281.     }
  282.     for (int i = 0 ; i < nthreads ; i++) {
  283.         threads[i].stop();
  284.     }
  285.     }
  286.  
  287.     /**
  288.      * Suspends all the Threads in this Thread group and all of its sub groups.
  289.      */
  290.     public final synchronized void suspend() {
  291.     checkAccess();
  292.     for (int i = 0 ; i < ngroups ; i++) {
  293.         groups[i].suspend();
  294.     }
  295.     for (int i = 0 ; i < nthreads ; i++) {
  296.         threads[i].suspend();
  297.     }
  298.     }
  299.  
  300.     /**
  301.      * Resumes all the Threads in this Thread group and all of its sub groups.
  302.      */
  303.     public final synchronized void resume() {
  304.     checkAccess();
  305.     for (int i = 0 ; i < ngroups ; i++) {
  306.         groups[i].resume();
  307.     }
  308.     for (int i = 0 ; i < nthreads ; i++) {
  309.         threads[i].resume();
  310.     }
  311.     }
  312.  
  313.     /**
  314.      * Destroys a Thread group. This does <b>NOT</b> stop the Threads
  315.      * in the Thread group.
  316.      * @exception IllegalThreadStateException If the Thread group is not empty
  317.      *         or if the Thread group was already destroyed.
  318.      */
  319.     public final synchronized void destroy() {
  320.     checkAccess();
  321.     if (destroyed || (nthreads > 0)) {
  322.         throw new IllegalThreadStateException();
  323.     }
  324.     while (ngroups > 0) {
  325.         groups[0].destroy();
  326.     }
  327.     if (parent != null) {
  328.         destroyed = true;
  329.         groups = null;
  330.         threads = null;
  331.         parent.remove(this);
  332.     }
  333.     }
  334.  
  335.     /**
  336.      * Adds the specified Thread group to this group.
  337.      * @param g the specified Thread group to be added
  338.      * @exception IllegalThreadStateException If the Thread group has been destroyed.
  339.      */
  340.     private final synchronized void add(ThreadGroup g){
  341.     if (destroyed) {
  342.         throw new IllegalThreadStateException();
  343.     }
  344.     if (groups == null) {
  345.         groups = new ThreadGroup[4];
  346.     } else if (ngroups == groups.length) {
  347.         ThreadGroup newgroups[] = new ThreadGroup[ngroups * 2];
  348.         System.arraycopy(groups, 0, newgroups, 0, ngroups);
  349.         groups = newgroups;
  350.     }
  351.     groups[ngroups] = g;
  352.  
  353.     // This is done last so it doesn't matter in case the
  354.     // thread is killed
  355.     ngroups++;
  356.     }
  357.  
  358.     /**
  359.      * Removes the specified Thread group from this group.
  360.      * @param g the Thread group to be removed
  361.      * @return if this Thread has already been destroyed.
  362.      */
  363.     private synchronized void remove(ThreadGroup g) {
  364.     if (destroyed) {
  365.         return;
  366.     }
  367.     for (int i = 0 ; i < ngroups ; i++) {
  368.         if (groups[i] == g) {
  369.         System.arraycopy(groups, i + 1, groups, i, --ngroups - i);
  370.         // Zap dangling reference to the dead group so that
  371.         // the garbage collector will collect it.
  372.         groups[ngroups] = null;
  373.         break;
  374.         }
  375.     }
  376.     if (nthreads == 0) {
  377.         notifyAll();
  378.     }
  379.     if (daemon && (nthreads == 0) && (ngroups == 0)) {
  380.         destroy();
  381.     }
  382.     }
  383.     
  384.     /**
  385.      * Adds the specified Thread to this group.
  386.      * @param t the Thread to be added
  387.      * @exception IllegalThreadStateException If the Thread group has been destroyed.
  388.      */
  389.     synchronized void add(Thread t) {
  390.     if (destroyed) {
  391.         throw new IllegalThreadStateException();
  392.     }
  393.     if (threads == null) {
  394.         threads = new Thread[4];
  395.     } else if (nthreads == threads.length) {
  396.         Thread newthreads[] = new Thread[nthreads * 2];
  397.         System.arraycopy(threads, 0, newthreads, 0, nthreads);
  398.         threads = newthreads;
  399.     }
  400.     threads[nthreads] = t;
  401.  
  402.     // This is done last so it doesn't matter in case the
  403.     // thread is killed
  404.     nthreads++;
  405.     }
  406.  
  407.     /**
  408.      * Removes the specified Thread from this group.
  409.      * @param t the Thread to be removed
  410.      * @return if the Thread has already been destroyed.
  411.      */
  412.     synchronized void remove(Thread t) {
  413.     if (destroyed) {
  414.         return;
  415.     }
  416.     for (int i = 0 ; i < nthreads ; i++) {
  417.         if (threads[i] == t) {
  418.         System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
  419.         // Zap dangling reference to the dead thread so that
  420.         // the garbage collector will collect it.
  421.         threads[nthreads] = null;
  422.         break;
  423.         }
  424.     }
  425.     if (nthreads == 0) {
  426.         notifyAll();
  427.     }
  428.     if (daemon && (nthreads == 0) && (ngroups == 0)) {
  429.         destroy();
  430.     }
  431.     }
  432.  
  433.     /**
  434.      * Lists this Thread group. Useful for debugging only.
  435.      */
  436.      public synchronized void list() {
  437.     list(System.out, 0);
  438.      }
  439.      void list(PrintStream out, int indent) {
  440.     for (int j = 0 ; j < indent ; j++) {
  441.         out.print(" ");
  442.     }
  443.     out.println(this);
  444.     indent += 4;
  445.     for (int i = 0 ; i < nthreads ; i++) {
  446.         for (int j = 0 ; j < indent ; j++) {
  447.         out.print(" ");
  448.         }
  449.         out.println(threads[i]);
  450.     }
  451.     for (int i = 0 ; i < ngroups ; i++) {
  452.         groups[i].list(out, indent);
  453.     }
  454.      }
  455.  
  456.     /**
  457.      * Returns a String representation of the Thread group.
  458.      */
  459.     public String toString() {
  460.     return getClass().getName() + "[name=" + getName() + ",maxpri=" + maxPriority + "]";
  461.     }
  462. }
  463.