/******************************************************************************* * Copyright (c) 2010 Robert "Unlogic" Olofsson (unlogic@unlogic.se). * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0-standalone.html ******************************************************************************/ package se.unlogic.standardutils.threads; import org.w3c.dom.Document; import org.w3c.dom.Element; import se.unlogic.standardutils.xml.Elementable; import se.unlogic.standardutils.xml.XMLAttribute; import se.unlogic.standardutils.xml.XMLElement; import se.unlogic.standardutils.xml.XMLGenerator; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @XMLElement(name="ExecutionController") public class SimpleExecutionController<T extends TaskGroup> implements ExecutionController<T>, Elementable{ private final ReentrantLock globalLock = new ReentrantLock(); private Condition finishedCondition = globalLock.newCondition(); private T taskGroup; private BlockingQueue<? extends Runnable> taskQueue; private ThreadPoolTaskGroupHandler<T> threadPoolTaskHandler; @XMLAttribute private boolean started; @XMLAttribute private boolean aborted; @XMLAttribute private int initialTaskCount; @XMLAttribute private AtomicInteger completedTaskCount = new AtomicInteger(); public SimpleExecutionController(T taskGroup, ThreadPoolTaskGroupHandler<T> threadPoolTaskHandler) { super(); this.taskGroup = taskGroup; this.taskQueue = taskGroup.getTasks(); this.threadPoolTaskHandler = threadPoolTaskHandler; initialTaskCount = taskQueue.size(); } public void abort() { globalLock.lock(); try{ if(this.threadPoolTaskHandler != null){ if(started){ threadPoolTaskHandler.remove(this); } this.aborted = true; this.executionComplete(); } }finally{ globalLock.unlock(); } } public void awaitExecution(long timeout) throws InterruptedException { globalLock.lock(); try{ if(finishedCondition != null){ finishedCondition.await(timeout, TimeUnit.MILLISECONDS); } }finally{ globalLock.unlock(); } } public void awaitExecution() throws InterruptedException { globalLock.lock(); try{ if(finishedCondition != null){ finishedCondition.await(); } }finally{ globalLock.unlock(); } } void executionComplete(){ globalLock.lock(); try{ if(finishedCondition != null){ finishedCondition.signalAll(); threadPoolTaskHandler = null; finishedCondition = null; } }finally{ globalLock.unlock(); } } public int getRemainingTaskCount() { return taskQueue.size(); } BlockingQueue<? extends Runnable> getTaskQueue() { return taskQueue; } public void start() { globalLock.lock(); try{ if(!started && !aborted){ this.threadPoolTaskHandler.add(this); this.started = true; } }finally{ globalLock.unlock(); } } public int getInitialTaskCount() { return initialTaskCount; } public int getCompletedTaskCount() { return completedTaskCount.get(); } void incrementCompletedTaskCount(){ this.completedTaskCount.incrementAndGet(); } public boolean isStarted(){ return started; } public boolean isAborted(){ return aborted; } public boolean isFinished(){ return started && !aborted && this.threadPoolTaskHandler == null; } public T getTaskGroup() { return taskGroup; } public Element toXML(Document doc) { return XMLGenerator.toXML(this, doc); } }