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  Changes    Path
  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 -0000      1.467
  +++ WHATSNEW  25 Jul 2003 11:02:52 -0000      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 -0000      1.11
  +++ parallel.html     25 Jul 2003 11:02:53 -0000      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>
   
  +
  +<h3>Parameters specified as nested elements</h3>
  +
  +<h4>daemons</h4>
  +<p>
  +The parallel task supports a &lt;daemons&gt; 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>
  +
  +<p>Daemon tasks can be used, for example, to start test servers which might 
not be easily
  +terminated from Ant. By using &lt;daemons&gt; such servers do not halt the 
build.
  +</p>
  +
  +
   <h3>Examples</h3>
   <pre>
   &lt;parallel&gt;
  
  
  
  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 -0000      1.22
  +++ Parallel.java     25 Jul 2003 11:02:53 -0000      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 */
  +    private TaskList daemonTasks;
  +
  +    /** Accumulation of exceptions messages from all nested tasks */
  +    private StringBuffer exceptionMessage;
  +
  +    /** Number of exceptions from nested tasks */
  +    private int numExceptions = 0;
  +
  +    /** The first exception encountered */
  +    private Throwable firstException;
  +
  +    /** The location of the first exception */
  +    private Location firstLocation;
  +
  +    /**
  +     * Add a group of daemon threads
  +     */
  +    public void addDaemons(TaskList daemonTasks) {
  +        if (this.daemonTasks != null) {
  +            throw new BuildException("Only one daemon group is supported");
  +        }
  +        this.daemonTasks = daemonTasks;
  +    }
  +
       /**
        * Interval to poll for completed threads when threadCount or
        * threadsPerProcessor is specified.  Integer in milliseconds.; optional
  @@ -211,6 +254,27 @@
           }
       }
   
  +    private void processExceptions(TaskRunnable[] runnables) {
  +        if (runnables == null) {
  +            return;
  +        }
  +        for (int i = 0; i < runnables.length; ++i) {
  +            Throwable t = runnables[i].getException();
  +            if (t != null) {
  +                numExceptions++;
  +                if (firstException == null) {
  +                    firstException = t;
  +                }
  +                if (t instanceof BuildException
  +                    && firstLocation == Location.UNKNOWN_LOCATION) {
  +                    firstLocation = ((BuildException) t).getLocation();
  +                }
  +                exceptionMessage.append(StringUtils.LINE_SEP);
  +                exceptionMessage.append(t.getMessage());
  +            }
  +        }
  +    }
  +
       /**
        * Spin up required threads with a maximum number active at any given 
time.
        *
  @@ -227,7 +291,7 @@
                threadNumber++) {
               Task nestedTask = (Task) e.nextElement();
               runnables[threadNumber]
  -                = new TaskRunnable(threadNumber, nestedTask);
  +                = new TaskRunnable(nestedTask);
           }
   
           final int maxRunning = numTasks < numThreads ? numTasks : numThreads;
  @@ -236,7 +300,23 @@
           threadNumber = 0;
           ThreadGroup group = new ThreadGroup("parallel");
   
  -        // now run them in limited numbers...
  +        TaskRunnable[] daemons = null;
  +        if (daemonTasks != null && daemonTasks.tasks.size() != 0) {
  +            daemons = new TaskRunnable[daemonTasks.tasks.size()];
  +        }
  +
  +        synchronized (semaphore) {
  +            // start any daemon threads
  +            if (daemons != null) {
  +                for (int i = 0; i < daemons.length; ++i) {
  +                    daemons[i] = new TaskRunnable((Task) 
daemonTasks.tasks.get(i));
  +                    Thread daemonThread =  new Thread(group, daemons[i]);
  +                    daemonThread.setDaemon(true);
  +                    daemonThread.start();
  +                }
  +            }
  +
  +            // now run main threads in limited numbers...
           // start initial batch of threads
           for (int i = 0; i < maxRunning; ++i) {
               running[i] = runnables[threadNumber++];
  @@ -266,7 +346,6 @@
           // now find available running slots for the remaining threads
           outer:
           while (threadNumber < numTasks && stillRunning) {
  -            synchronized (semaphore) {
                   for (int i = 0; i < maxRunning; i++) {
                       if (running[i] == null || running[i].finished) {
                           running[i] = runnables[threadNumber++];
  @@ -288,9 +367,7 @@
                       // sheesh!
                   }
               }
  -        }
   
  -        synchronized (semaphore) {
               // are all threads finished
               outer2:
               while (stillRunning) {
  @@ -315,25 +392,12 @@
           }
   
           // 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 < numTasks; ++i) {
  -            Throwable t = runnables[i].getException();
  -            if (t != null) {
  -                numExceptions++;
  -                if (firstException == null) {
  -                    firstException = t;
  -                }
  -                if (t instanceof BuildException
  -                    && firstLocation == Location.UNKNOWN_LOCATION) {
  -                    firstLocation = ((BuildException) t).getLocation();
  -                }
  -                exceptionMessage.append(StringUtils.LINE_SEP);
  -                exceptionMessage.append(t.getMessage());
  -            }
  -        }
  +        exceptionMessage = new StringBuffer();
  +        numExceptions = 0;
  +        firstException = null;
  +        firstLocation = Location.UNKNOWN_LOCATION;
  +        processExceptions(daemons);
  +        processExceptions(runnables);
   
           if (numExceptions == 1) {
               if (firstException instanceof BuildException) {
  @@ -373,7 +437,6 @@
       private class TaskRunnable implements Runnable {
           private Throwable exception;
           private Task task;
  -        private int taskNumber;
           boolean finished;
   
           /**
  @@ -381,9 +444,8 @@
            *
            * @param task the Task to be executed in a seperate thread
            */
  -        TaskRunnable(int taskNumber, Task task) {
  +        TaskRunnable(Task task) {
               this.task = task;
  -            this.taskNumber = taskNumber;
           }
   
           /**
  
  
  

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

Reply via email to