org.testng.internal.thread.graph.GraphThreadPoolExecutor Maven / Gradle / Ivy
package org.testng.internal.thread.graph;
import org.testng.TestNGException;
import org.testng.internal.DynamicGraph;
import org.testng.internal.DynamicGraph.Status;
import org.testng.internal.thread.TestNGThreadFactory;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* An Executor that launches tasks per batches. It takes a {@code DynamicGraph}
* of tasks to be run and a {@code IThreadWorkerFactory} to initialize/create
* {@code Runnable} wrappers around those tasks
*/
public class GraphThreadPoolExecutor extends ThreadPoolExecutor {
private final DynamicGraph m_graph;
private final Queue m_activeRunnables = new ConcurrentLinkedDeque<>();
private final IThreadWorkerFactory m_factory;
public GraphThreadPoolExecutor(String name, DynamicGraph graph, IThreadWorkerFactory factory, int corePoolSize,
int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, new TestNGThreadFactory(name));
m_graph = graph;
m_factory = factory;
if (m_graph.getFreeNodes().isEmpty()) {
throw new TestNGException("The graph of methods contains a cycle:" + graph.getEdges());
}
}
public void run() {
synchronized(m_graph) {
List freeNodes = m_graph.getFreeNodes();
runNodes(freeNodes);
}
}
/**
* Create one worker per node and execute them.
*/
private void runNodes(List freeNodes) {
List> runnables = m_factory.createWorkers(freeNodes);
for (IWorker r : runnables) {
m_activeRunnables.add(r);
setStatus(r, Status.RUNNING);
try {
execute(r);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
}
private void setStatus(IWorker worker, Status status) {
if (status == Status.FINISHED) {
m_activeRunnables.remove(worker);
}
synchronized(m_graph) {
for (T m : worker.getTasks()) {
m_graph.setStatus(m, status);
}
}
}
@Override
public void afterExecute(Runnable r, Throwable t) {
setStatus((IWorker) r, Status.FINISHED);
synchronized(m_graph) {
if (m_graph.getNodeCount() == m_graph.getNodeCountWithStatus(Status.FINISHED)) {
shutdown();
} else {
List freeNodes = m_graph.getFreeNodes();
runNodes(freeNodes);
}
}
}
}