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 <daemons> 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 <daemons> such servers do not halt the
build.
+</p>
+
+
<h3>Examples</h3>
<pre>
<parallel>
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]