cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2004-12-11 Thread jkf
jkf 2004/12/11 02:49:01

  Modified:src/main/org/apache/tools/ant/taskdefs Tag: ANT_16_BRANCH
Parallel.java
  Log:
  Sync
  
  Revision  ChangesPath
  No   revision
  No   revision
  1.24.2.6  +23 -5 ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.24.2.5
  retrieving revision 1.24.2.6
  diff -u -r1.24.2.5 -r1.24.2.6
  --- Parallel.java 1 Apr 2004 13:07:34 -   1.24.2.5
  +++ Parallel.java 11 Dec 2004 10:49:01 -  1.24.2.6
  @@ -56,9 +56,10 @@
   /**
* Add a nested task to execute parallel (asynchron).
* p
  - * @param nestedTask  Nested task to be executed in parallel
  + * @param nestedTask  Nested task to be executed in parallel.
  + *must not be null.
*/
  -public void addTask(Task nestedTask) throws BuildException {
  +public void addTask(Task nestedTask) {
   tasks.add(nestedTask);
   }
   }
  @@ -107,6 +108,7 @@
   
   /**
* Add a group of daemon threads
  + * @param daemonTasks The tasks to be executed as daemon.
*/
   public void addDaemons(TaskList daemonTasks) {
   if (this.daemonTasks != null) {
  @@ -266,6 +268,14 @@
   }
   
   synchronized (semaphore) {
  +// When we leave this block we can be sure all data is really
  +// stored in main memory before the new threads start, the new
  +// threads will for sure load the data from main memory.
  +//
  +// This probably is slightly paranoid.
  +}
  +
  +synchronized (semaphore) {
   // start any daemon threads
   if (daemons != null) {
   for (int i = 0; i  daemons.length; ++i) {
  @@ -307,7 +317,7 @@
   outer:
   while (threadNumber  numTasks  stillRunning) {
   for (int i = 0; i  maxRunning; i++) {
  -if (running[i] == null || running[i].finished) {
  +if (running[i] == null || running[i].isFinished()) {
   running[i] = runnables[threadNumber++];
   Thread thread =  new Thread(group, running[i]);
   thread.start();
  @@ -332,7 +342,7 @@
   outer2:
   while (stillRunning) {
   for (int i = 0; i  maxRunning; ++i) {
  -if (running[i] != null  !running[i].finished) {
  +if (running[i] != null  !running[i].isFinished()) {
   //System.out.println(Thread  + i +  is still 
alive );
   // still running - wait for it
   try {
  @@ -397,7 +407,7 @@
   private class TaskRunnable implements Runnable {
   private Throwable exception;
   private Task task;
  -boolean finished;
  +private boolean finished;
   
   /**
* Construct a new TaskRunnable.p
  @@ -434,6 +444,14 @@
*/
   public Throwable getException() {
   return exception;
  +}
  +
  +/**
  + * Provides the indicator that the task has been finished.
  + * @return Returns true when the task is finished.
  + */
  +boolean isFinished() {
  +return finished;
   }
   }
   
  
  
  

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2004-12-10 Thread jkf
jkf 2004/12/09 14:17:24

  Modified:src/main/org/apache/tools/ant/taskdefs Parallel.java
  Log:
  In bug 32566 someone asked about the thread safety requirements in Ant.
  This made me perform a quick check on the main flow of the Ant project
  from a threading perspective. The only cause for wich the tasks specified
  in the build file may be executed in another thread is the parallel task.
  The parallel task does not ensure all variables are stored in memory before
  the new threads start.
  
  Revision  ChangesPath
  1.30  +8 -0  ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- Parallel.java 1 Apr 2004 13:06:45 -   1.29
  +++ Parallel.java 9 Dec 2004 22:17:24 -   1.30
  @@ -266,6 +266,14 @@
   }
   
   synchronized (semaphore) {
  +// When we leave this block we can be sure all data is really 
  +// stored in main memory before the new threads start, the new 
  +// threads will for sure load the data from main memory.
  +//
  +// This probably is slightly paranoid.
  +}
  +
  +synchronized (semaphore) {
   // start any daemon threads
   if (daemons != null) {
   for (int i = 0; i  daemons.length; ++i) {
  
  
  

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2004-12-10 Thread jkf
jkf 2004/12/09 15:06:47

  Modified:src/main/org/apache/tools/ant/taskdefs Parallel.java
  Log:
  Checkstyle updates.
  (removed trailing spaces just added, updated javadoc, removed an undocumented 
BuildException
  which was neither thrown according to interface nor according to methods 
implementation.)
  
  Revision  ChangesPath
  1.31  +18 -8 ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Parallel.java 9 Dec 2004 22:17:24 -   1.30
  +++ Parallel.java 9 Dec 2004 23:06:47 -   1.31
  @@ -56,9 +56,10 @@
   /**
* Add a nested task to execute parallel (asynchron).
* p
  - * @param nestedTask  Nested task to be executed in parallel
  + * @param nestedTask  Nested task to be executed in parallel.
  + *must not be null.
*/
  -public void addTask(Task nestedTask) throws BuildException {
  +public void addTask(Task nestedTask) {
   tasks.add(nestedTask);
   }
   }
  @@ -107,6 +108,7 @@
   
   /**
* Add a group of daemon threads
  + * @param daemonTasks The tasks to be executed as daemon.
*/
   public void addDaemons(TaskList daemonTasks) {
   if (this.daemonTasks != null) {
  @@ -266,13 +268,13 @@
   }
   
   synchronized (semaphore) {
  -// When we leave this block we can be sure all data is really 
  -// stored in main memory before the new threads start, the new 
  +// When we leave this block we can be sure all data is really
  +// stored in main memory before the new threads start, the new
   // threads will for sure load the data from main memory.
   //
   // This probably is slightly paranoid.
   }
  -
  +
   synchronized (semaphore) {
   // start any daemon threads
   if (daemons != null) {
  @@ -315,7 +317,7 @@
   outer:
   while (threadNumber  numTasks  stillRunning) {
   for (int i = 0; i  maxRunning; i++) {
  -if (running[i] == null || running[i].finished) {
  +if (running[i] == null || running[i].isFinished()) {
   running[i] = runnables[threadNumber++];
   Thread thread =  new Thread(group, running[i]);
   thread.start();
  @@ -340,7 +342,7 @@
   outer2:
   while (stillRunning) {
   for (int i = 0; i  maxRunning; ++i) {
  -if (running[i] != null  !running[i].finished) {
  +if (running[i] != null  !running[i].isFinished()) {
   //System.out.println(Thread  + i +  is still 
alive );
   // still running - wait for it
   try {
  @@ -405,7 +407,7 @@
   private class TaskRunnable implements Runnable {
   private Throwable exception;
   private Task task;
  -boolean finished;
  +private boolean finished;
   
   /**
* Construct a new TaskRunnable.p
  @@ -442,6 +444,14 @@
*/
   public Throwable getException() {
   return exception;
  +}
  +
  +/**
  + * Provides the indicator that the task has been finished.
  + * @return Returns true when the task is finished.
  + */
  +boolean isFinished() {
  +return finished;
   }
   }
   
  
  
  

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2004-04-01 Thread peterreilly
peterreilly2004/04/01 05:07:34

  Modified:.Tag: ANT_16_BRANCH WHATSNEW
   src/main/org/apache/tools/ant/taskdefs Tag: ANT_16_BRANCH
Parallel.java
  Log:
  sync with HEAD
  
  Revision  ChangesPath
  No   revision
  No   revision
  1.503.2.64 +2 -0  ant/WHATSNEW
  
  Index: WHATSNEW
  ===
  RCS file: /home/cvs/ant/WHATSNEW,v
  retrieving revision 1.503.2.63
  retrieving revision 1.503.2.64
  diff -u -r1.503.2.63 -r1.503.2.64
  --- WHATSNEW  31 Mar 2004 11:45:42 -  1.503.2.63
  +++ WHATSNEW  1 Apr 2004 13:07:34 -   1.503.2.64
  @@ -104,6 +104,8 @@
   
   * wrong compare used in ProjectComponent for logging. Bugzilla Report 28070.
   
  +* failOnAny attribute for parallel was broken. Bugzilla Report 28122.
  +
   Other changes:
   --
   
  
  
  
  No   revision
  No   revision
  1.24.2.5  +3 -3  ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.24.2.4
  retrieving revision 1.24.2.5
  diff -u -r1.24.2.4 -r1.24.2.5
  --- Parallel.java 9 Mar 2004 17:01:34 -   1.24.2.4
  +++ Parallel.java 1 Apr 2004 13:07:34 -   1.24.2.5
  @@ -417,12 +417,12 @@
   task.perform();
   } catch (Throwable t) {
   exception = t;
  +if (failOnAny) {
  +stillRunning = false;
  +}
   } finally {
   synchronized (semaphore) {
   finished = true;
  -if (failOnAny) {
  -stillRunning = false;
  -}
   semaphore.notifyAll();
   }
   }
  
  
  

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2003-07-25 Thread conor
conor   2003/07/25 04:02:53

  Modified:.WHATSNEW
   docs/manual/CoreTasks parallel.html
   src/main/org/apache/tools/ant/taskdefs Parallel.java
  Log:
  Add daemons element to parallel to start daemon threads which
  continue to run after the parallel task has completed.
  
  Revision  ChangesPath
  1.468 +10 -2 ant/WHATSNEW
  
  Index: WHATSNEW
  ===
  RCS file: /home/cvs/ant/WHATSNEW,v
  retrieving revision 1.467
  retrieving revision 1.468
  diff -u -w -u -r1.467 -r1.468
  --- WHATSNEW  25 Jul 2003 10:06:31 -  1.467
  +++ WHATSNEW  25 Jul 2003 11:02:52 -  1.468
  @@ -515,6 +515,14 @@
   
   * exec will now work on OpenVMS (please read the notes in
 exec's manual page).  Bugzilla Report 21877.  
  +
  +* parallel now supports a timeout which can be used to recover
  +  from deadlocks, etc in the parallel threads. parallel also
  +  now supports a daemons nested element. This can be used to
  +  run tasks in daemon threads which the parallel task will not
  +  wait for before completing. A new attribute failonany will cause
  +  parallel to throw an exception if any thread fails without
  +  waiting for all other threads to complete.
   
   Changes from Ant 1.5.2 to Ant 1.5.3
   ===
  
  
  
  1.12  +19 -0 ant/docs/manual/CoreTasks/parallel.html
  
  Index: parallel.html
  ===
  RCS file: /home/cvs/ant/docs/manual/CoreTasks/parallel.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -u -r1.11 -r1.12
  --- parallel.html 24 Jul 2003 14:24:07 -  1.11
  +++ parallel.html 25 Jul 2003 11:02:53 -  1.12
  @@ -99,6 +99,25 @@
   would occur.  This is not a repalcement for Java Language level thread
   semantics and is best used for embarassingly parallel tasks./p
   
  +
  +h3Parameters specified as nested elements/h3
  +
  +h4daemons/h4
  +p
  +The parallel task supports a lt;daemonsgt; nested element. This is a list 
of tasks
  +which are to be run in parallel daemon threads. The parallel task will not 
wait for
  +these tasks to complete. Being daemon threads, however, they will not 
prevent Ant from
  +completing, whereupon the threads are terminated. Failures in daemon threads 
which
  +occur before the parallel task itself finishes will be reported and can cause
  +parallel to throw an exception. Failures which occur after parallel has 
completed are not
  +reported.
  +/p
  +
  +pDaemon tasks can be used, for example, to start test servers which might 
not be easily
  +terminated from Ant. By using lt;daemonsgt; such servers do not halt the 
build.
  +/p
  +
  +
   h3Examples/h3
   pre
   lt;parallelgt;
  
  
  
  1.23  +116 -54   ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -w -u -r1.22 -r1.23
  --- Parallel.java 25 Jul 2003 08:59:39 -  1.22
  +++ Parallel.java 25 Jul 2003 11:02:53 -  1.23
  @@ -56,6 +56,8 @@
   import java.lang.reflect.Method;
   import java.util.Enumeration;
   import java.util.Vector;
  +import java.util.List;
  +import java.util.ArrayList;
   import org.apache.tools.ant.BuildException;
   import org.apache.tools.ant.Location;
   import org.apache.tools.ant.Task;
  @@ -86,6 +88,21 @@
   public class Parallel extends Task
 implements TaskContainer {
   
  +/** Class which holds a list of tasks to execute */
  +public static class TaskList implements TaskContainer {
  +/** Collection holding the nested tasks */
  +private List tasks = new ArrayList();
  +
  +/**
  + * Add a nested task to execute parallel (asynchron).
  + * p
  + * @param nestedTask  Nested task to be executed in parallel
  + */
  +public void addTask(Task nestedTask) throws BuildException {
  +tasks.add(nestedTask);
  +}
  +}
  +
   /** Collection holding the nested tasks */
   private Vector nestedTasks = new Vector();
   
  @@ -98,12 +115,13 @@
   /** Total number of threads per processor to run.  */
   private int numThreadsPerProcessor = 0;
   
  +/** The timeout period in milliseconds */
   private long timeout;
   
   /** Indicates threads are still running and new threads can be issued */
   private volatile boolean stillRunning;
   
  -/** INdicates that the execution timedout */
  +/** Indicates that the execution timedout */
   private boolean timedOut;
   
   /**
  @@ -112,6 +130,31 @@
*/
   private boolean failOnAny;
   
  +/** The dameon task list if any */
  +

cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2003-04-14 Thread conor
conor   2003/04/14 04:58:04

  Modified:.check.xml
   src/main/org/apache/tools/ant IntrospectionHelper.java
Project.java RuntimeConfigurable.java
   src/main/org/apache/tools/ant/filters BaseFilterReader.java
EscapeUnicode.java StripLineComments.java
   src/main/org/apache/tools/ant/filters/util
ChainReaderHelper.java
   src/main/org/apache/tools/ant/helper ProjectHelperImpl.java
   src/main/org/apache/tools/ant/taskdefs Parallel.java
  Log:
  style fixes
  
  Revision  ChangesPath
  1.5   +7 -7  ant/check.xml
  
  Index: check.xml
  ===
  RCS file: /home/cvs/ant/check.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -w -u -r1.4 -r1.5
  --- check.xml 8 Jan 2003 08:29:10 -   1.4
  +++ check.xml 14 Apr 2003 11:58:02 -  1.5
  @@ -6,10 +6,10 @@
 target name=checkstyle
   taskdef name=checkstyle
classname=com.puppycrawl.tools.checkstyle.CheckStyleTask/
  -checkstyle
  -  property key=checkstyle.header.file 
file=src/etc/RequiredHeader.txt/
  -  property key=checkstyle.header.ignoreline value=4/
  -  property key=checkstyle.javadoc.scope value=${javadoc.scope}/
  +checkstyle headerFile=src/etc/RequiredHeader.txt
  +headerIgnoreLine=4
  +allowProtected=true
  +javadocScope=${javadoc.scope}
 fileset dir=${java.dir}
   include name=${tocheck}/
 /fileset
  
  
  
  1.52  +1 -2  
ant/src/main/org/apache/tools/ant/IntrospectionHelper.java
  
  Index: IntrospectionHelper.java
  ===
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/IntrospectionHelper.java,v
  retrieving revision 1.51
  retrieving revision 1.52
  diff -u -w -u -r1.51 -r1.52
  --- IntrospectionHelper.java  6 Apr 2003 09:30:56 -   1.51
  +++ IntrospectionHelper.java  14 Apr 2003 11:58:03 -  1.52
  @@ -436,8 +436,7 @@
   DynamicConfigurator dc = (DynamicConfigurator) element;
   dc.setDynamicAttribute(attributeName, value);
   return;
  -}
  -else {
  +} else {
   String msg = getElementName(p, element) +
doesn't support the \ + attributeName +
   \ attribute.;
  
  
  
  1.134 +49 -34ant/src/main/org/apache/tools/ant/Project.java
  
  Index: Project.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/Project.java,v
  retrieving revision 1.133
  retrieving revision 1.134
  diff -u -w -u -r1.133 -r1.134
  --- Project.java  3 Apr 2003 14:44:01 -   1.133
  +++ Project.java  14 Apr 2003 11:58:03 -  1.134
  @@ -903,8 +903,7 @@
oldLoader instanceof AntClassLoader
newLoader instanceof AntClassLoader
((AntClassLoader) oldLoader).getClasspath()
  -.equals(((AntClassLoader) newLoader).getClasspath())
  -) {
  +.equals(((AntClassLoader) 
newLoader).getClasspath())) {
   // same classname loaded from the same
   // classpath components
   logLevel = MSG_VERBOSE;
  @@ -2171,7 +2170,7 @@
   // Should move to a separate public class - and have API to add
   // listeners, etc.
   private static class AntRefTable extends Hashtable {
  -Project project;
  +private Project project;
   public AntRefTable(Project project) {
   super();
   this.project = project;
  @@ -2212,9 +2211,9 @@
   }
   
   private static class AntTaskTable extends LazyHashtable {
  -Project project;
  -Properties props;
  -boolean tasks = false;
  +private Project project;
  +private Properties props;
  +private boolean tasks = false;
   
   public AntTaskTable(Project p, boolean tasks) {
   this.project = p;
  @@ -2226,26 +2225,33 @@
   }
   
   protected void initAll() {
  -if (initAllDone ) return;
  +if (initAllDone) {
  +return;
  +}
   project.log(InitAll, Project.MSG_DEBUG);
  -if (props==null ) return;
  +if (props == null) {
  +return;
  +}
   Enumeration enum = props.propertyNames();
   while (enum.hasMoreElements()) {
   String key = (String) enum.nextElement();
   Class taskClass=getTask( key );
   if (taskClass!=null ) 

cvs commit: ant/src/main/org/apache/tools/ant/taskdefs Parallel.java

2003-04-07 Thread conor
conor   2003/04/07 07:47:02

  Modified:src/main/org/apache/tools/ant/taskdefs Parallel.java
  Log:
  Remove duplication in Parallel
  
  Revision  ChangesPath
  1.16  +19 -82ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java
  
  Index: Parallel.java
  ===
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Parallel.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -w -u -r1.15 -r1.16
  --- Parallel.java 11 Feb 2003 11:26:44 -  1.15
  +++ Parallel.java 7 Apr 2003 14:47:02 -   1.16
  @@ -150,13 +150,12 @@
   public void execute() throws BuildException {
   updateThreadCounts();
   if (numThreads == 0) {
  -spinAllThreads();
  -} else {
  -spinNumThreads();
  +numThreads = nestedTasks.size();
   }
  +spinThreads();
   }
   
  -public void updateThreadCounts() {
  +private void updateThreadCounts() {
   if (numThreadsPerProcessor != 0) {
   int numProcessors = getNumProcessors();
   if (numProcessors != 0) {
  @@ -168,18 +167,19 @@
   /**
* Spin up threadCount threads.
*/
  -public void spinNumThreads() throws BuildException {
  -final int maxThreads = nestedTasks.size();
  -Thread[] threads = new Thread[maxThreads];
  -TaskThread[] taskThreads = new TaskThread[maxThreads];
  +private void spinThreads() throws BuildException {
  +final int numTasks = nestedTasks.size();
  +Thread[] threads = new Thread[numTasks];
  +TaskRunnable[] runnables = new TaskRunnable[numTasks];
   int threadNumber = 0;
   for (Enumeration e = nestedTasks.elements(); e.hasMoreElements(); 
threadNumber++) {
   Task nestedTask = (Task) e.nextElement();
   ThreadGroup group = new ThreadGroup(parallel);
  -TaskThread taskThread = new TaskThread(threadNumber, nestedTask);
  -taskThreads[threadNumber] = taskThread;
  -threads[threadNumber] = new Thread(group, taskThread);
  +TaskRunnable taskRunnable 
  += new TaskRunnable(threadNumber, nestedTask);
  +runnables[threadNumber] = taskRunnable;
  +threads[threadNumber] = new Thread(group, taskRunnable);
   }
   
   final int maxRunning = numThreads;
  @@ -188,7 +188,7 @@
   
   // now run them in limited numbers...
   outer:
  -while (threadNumber  maxThreads) {
  +while (threadNumber  numTasks) {
   synchronized(semaphore) {
   for (int i = 0; i  maxRunning; i++) {
   if (running[i] == null || !running[i].isAlive()) {
  @@ -225,8 +225,8 @@
   int numExceptions = 0;
   Throwable firstException = null;
   Location firstLocation = Location.UNKNOWN_LOCATION;;
  -for (int i = 0; i  maxThreads; ++i) {
  -Throwable t = taskThreads[i].getException();
  +for (int i = 0; i  numTasks; ++i) {
  +Throwable t = runnables[i].getException();
   if (t != null) {
   numExceptions++;
   if (firstException == null) {
  @@ -253,71 +253,7 @@
   }
   }
   
  -/**
  - * Spin up one thread per task.
  - */
  -public void spinAllThreads() throws BuildException {
  -int numTasks = nestedTasks.size();
  -Thread[] threads = new Thread[numTasks];
  -TaskThread[] taskThreads = new TaskThread[numTasks];
  -int threadNumber = 0;
  -for (Enumeration e = nestedTasks.elements(); e.hasMoreElements(); 
  - threadNumber++) {
  -Task nestedTask = (Task) e.nextElement();
  -ThreadGroup group = new ThreadGroup(parallel);
  -TaskThread taskThread = new TaskThread(threadNumber, nestedTask);
  -taskThreads[threadNumber] = taskThread;
  -threads[threadNumber] = new Thread(group, taskThread);
  -}
  -
  -// now start all threads
  -for (int i = 0; i  threads.length; ++i) {
  -threads[i].start();
  -}
  -
  -// now join to all the threads 
  -for (int i = 0; i  threads.length; ++i) {
  -try {
  -threads[i].join();
  -} catch (InterruptedException ie) {
  -// who would interrupt me at a time like this?
  -}
  -}
  -
  -// now did any of the threads throw an exception
  -StringBuffer exceptionMessage = new StringBuffer();
  -int numExceptions = 0;
  -Throwable firstException = null;
  -Location firstLocation = Location.UNKNOWN_LOCATION;;
  -for (int i = 0; i  threads.length; ++i) {
  -