diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Parallel.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Parallel.java | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Parallel.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Parallel.java deleted file mode 100644 index c4f5c9e9..00000000 --- a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/Parallel.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package org.apache.tools.ant.taskdefs; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; -import java.util.Vector; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.ExitStatusException; -import org.apache.tools.ant.Location; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.TaskContainer; -import org.apache.tools.ant.property.LocalProperties; -import org.apache.tools.ant.util.StringUtils; - -/** - * Executes the contained tasks in separate threads, continuing - * once all are completed. - * <p> - * New behavior allows for the ant script to specify a maximum number of - * threads that will be executed in parallel. One should be very careful about - * using the <code>waitFor</code> task when specifying <code>threadCount</code> - * as it can cause deadlocks if the number of threads is too small or if one of - * the nested tasks fails to execute completely. The task selection algorithm - * will insure that the tasks listed before a task have started before that - * task is started, but it will not insure a successful completion of those - * tasks or that those tasks will finish first (i.e. it's a classic race - * condition). - * </p> - * @since Ant 1.4 - * - * @ant.task category="control" - */ -public class Parallel extends Task - implements TaskContainer { - - private static final int NUMBER_TRIES = 100; - - /** 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. - * must not be null. - */ - public void addTask(Task nestedTask) { - tasks.add(nestedTask); - } - } - - /** Collection holding the nested tasks */ - private Vector nestedTasks = new Vector(); - - /** Semaphore to notify of completed threads */ - private final Object semaphore = new Object(); - - /** Total number of threads to run */ - private int numThreads = 0; - - /** 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 */ - private boolean timedOut; - - /** - * Indicates whether failure of any of the nested tasks should end - * execution - */ - 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; - - /** The status of the first ExitStatusException. */ - private Integer firstExitStatus; - - /** - * Add a group of daemon threads - * @param daemonTasks The tasks to be executed as daemon. - */ - 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 - * - * @param pollInterval New value of property pollInterval. - */ - public void setPollInterval(int pollInterval) { - } - - /** - * Control whether a failure in a nested task halts execution. Note that - * the task will complete but existing threads will continue to run - they - * are not stopped - * - * @param failOnAny if true any nested task failure causes parallel to - * complete. - */ - public void setFailOnAny(boolean failOnAny) { - this.failOnAny = failOnAny; - } - - /** - * Add a nested task to execute in parallel. - * @param nestedTask Nested task to be executed in parallel - */ - public void addTask(Task nestedTask) { - nestedTasks.addElement(nestedTask); - } - - /** - * Dynamically generates the number of threads to execute based on the - * number of available processors (via - * <code>java.lang.Runtime.availableProcessors()</code>). - * Will overwrite the value set in threadCount; optional - * @param numThreadsPerProcessor Number of threads to create per available - * processor. - * - */ - public void setThreadsPerProcessor(int numThreadsPerProcessor) { - this.numThreadsPerProcessor = numThreadsPerProcessor; - } - - /** - * Statically determine the maximum number of tasks to execute - * simultaneously. If there are less tasks than threads then all will be - * executed at once, if there are more then only <code>threadCount</code> - * tasks will be executed at one time. If <code>threadsPerProcessor</code> - * is set then this value is - * ignored.; optional - * - * @param numThreads total number of threads. - * - */ - public void setThreadCount(int numThreads) { - this.numThreads = numThreads; - } - - /** - * Sets the timeout on this set of tasks. If the timeout is reached - * before the other threads complete, the execution of this - * task completes with an exception. - * - * Note that existing threads continue to run. - * - * @param timeout timeout in milliseconds. - */ - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - - - /** - * Execute the parallel tasks - * - * @exception BuildException if any of the threads failed. - */ - public void execute() throws BuildException { - updateThreadCounts(); - if (numThreads == 0) { - numThreads = nestedTasks.size(); - } - spinThreads(); - } - - /** - * Determine the number of threads based on the number of processors - */ - private void updateThreadCounts() { - if (numThreadsPerProcessor != 0) { - numThreads = Runtime.getRuntime().availableProcessors() * - numThreadsPerProcessor; - } - } - - 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(); - } - if (t instanceof ExitStatusException - && firstExitStatus == null) { - ExitStatusException ex = (ExitStatusException) t; - firstExitStatus = ex.getStatus(); - // potentially overwriting existing value but the - // location should match the exit status - firstLocation = ex.getLocation(); - } - exceptionMessage.append(StringUtils.LINE_SEP); - exceptionMessage.append(t.getMessage()); - } - } - } - - /** - * Spin up required threads with a maximum number active at any given time. - * - * @exception BuildException if any of the threads failed. - */ - private void spinThreads() throws BuildException { - final int numTasks = nestedTasks.size(); - TaskRunnable[] runnables = new TaskRunnable[numTasks]; - stillRunning = true; - timedOut = false; - boolean interrupted = false; - - int threadNumber = 0; - for (Enumeration e = nestedTasks.elements(); e.hasMoreElements(); - threadNumber++) { - Task nestedTask = (Task) e.nextElement(); - runnables[threadNumber] - = new TaskRunnable(nestedTask); - } - - final int maxRunning = numTasks < numThreads ? numTasks : numThreads; - TaskRunnable[] running = new TaskRunnable[maxRunning]; - - threadNumber = 0; - ThreadGroup group = new ThreadGroup("parallel"); - - TaskRunnable[] daemons = null; - if (daemonTasks != null && daemonTasks.tasks.size() != 0) { - daemons = new TaskRunnable[daemonTasks.tasks.size()]; - } - - 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) { - 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++]; - Thread thread = new Thread(group, running[i]); - thread.start(); - } - - if (timeout != 0) { - // start the timeout thread - Thread timeoutThread = new Thread() { - public synchronized void run() { - try { - wait(timeout); - synchronized (semaphore) { - stillRunning = false; - timedOut = true; - semaphore.notifyAll(); - } - } catch (InterruptedException e) { - // ignore - } - } - }; - timeoutThread.start(); - } - - try { - // now find available running slots for the remaining threads - outer: while (threadNumber < numTasks && stillRunning) { - for (int i = 0; i < maxRunning; i++) { - if (running[i] == null || running[i].isFinished()) { - running[i] = runnables[threadNumber++]; - Thread thread = new Thread(group, running[i]); - thread.start(); - // continue on outer while loop to get another - // available slot - continue outer; - } - } - - // if we got here all slots in use, so sleep until - // something happens - semaphore.wait(); - } - - // are all threads finished - outer2: while (stillRunning) { - for (int i = 0; i < maxRunning; ++i) { - if (running[i] != null && !running[i].isFinished()) { - // System.out.println("Thread " + i + " is still - // alive "); - // still running - wait for it - semaphore.wait(); - continue outer2; - } - } - stillRunning = false; - } - } catch (InterruptedException ie) { - interrupted = true; - } - - if (!timedOut && !failOnAny) { - // https://issues.apache.org/bugzilla/show_bug.cgi?id=49527 - killAll(running); - } - } - - if (interrupted) { - throw new BuildException("Parallel execution interrupted."); - } - if (timedOut) { - throw new BuildException("Parallel execution timed out"); - } - - // now did any of the threads throw an exception - exceptionMessage = new StringBuffer(); - numExceptions = 0; - firstException = null; - firstExitStatus = null; - firstLocation = Location.UNKNOWN_LOCATION; - processExceptions(daemons); - processExceptions(runnables); - - if (numExceptions == 1) { - if (firstException instanceof BuildException) { - throw (BuildException) firstException; - } else { - throw new BuildException(firstException); - } - } else if (numExceptions > 1) { - if (firstExitStatus == null) { - throw new BuildException(exceptionMessage.toString(), - firstLocation); - } else { - throw new ExitStatusException(exceptionMessage.toString(), - firstExitStatus, firstLocation); - } - } - } - - /** - * Doesn't do anything if all threads where already gone, - * else it tries to interrupt the threads 100 times. - * @param running The list of tasks that may currently be running. - */ - private void killAll(TaskRunnable[] running) { - boolean oneAlive; - int tries = 0; - do { - oneAlive = false; - for (int i = 0; i < running.length; i++) { - if (running[i] != null && !running[i].isFinished()) { - running[i].interrupt(); - Thread.yield(); - oneAlive = true; - } - } - if (oneAlive) { - tries++; - Thread.yield(); - } - } while (oneAlive && tries < NUMBER_TRIES); - } - - /** - * thread that execs a task - */ - private class TaskRunnable implements Runnable { - private Throwable exception; - private Task task; - private boolean finished; - private volatile Thread thread; - - /** - * Construct a new TaskRunnable.<p> - * - * @param task the Task to be executed in a separate thread - */ - TaskRunnable(Task task) { - this.task = task; - } - - /** - * Executes the task within a thread and takes care about - * Exceptions raised within the task. - */ - public void run() { - try { - LocalProperties.get(getProject()).copy(); - thread = Thread.currentThread(); - task.perform(); - } catch (Throwable t) { - exception = t; - if (failOnAny) { - stillRunning = false; - } - } finally { - synchronized (semaphore) { - finished = true; - semaphore.notifyAll(); - } - } - } - - /** - * get any exception that got thrown during execution; - * @return an exception or null for no exception/not yet finished - */ - 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; - } - - void interrupt() { - thread.interrupt(); - } - } - -} |