/*
Copyright (C) 2011 Diego Darriba, David Posada
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package es.uvigo.darwin.jmodeltest.exe;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import es.uvigo.darwin.jmodeltest.model.Model;
import es.uvigo.darwin.jmodeltest.observer.ProgressInfo;
public class PhymlParallelModel extends Observable implements Observer {
/** The runtime **/
private Runtime runtime = Runtime.getRuntime();
/** The size of parallel tasks **/
private int maxNumberOfTasks;
/** The list of model estimators **/
private List<PhymlSingleModel> estimatorList;
/** The pool of threads **/
private ExecutorService threadPool;
/** Collection of callable objects (tasks) **/
private Collection<Callable<Object>> c = new ArrayList<Callable<Object>>();
/**
* Instantiates a new PhymlParallelModel with no models to optimize.
* The size of the thread pool is equal to the number of available cores in the machine.
*
* @param alignment the common alignment of the models
*/
public PhymlParallelModel() {
this(-1);
}
/**
* Instantiates a new PhymlParallelModel with no models to optimize and
* a fixed size of the thread pool
*
* @param availableThreads the size of the thread pool
* @param alignment the common alignment of the models
*/
public PhymlParallelModel(int availableThreads) {
if (availableThreads < 0) {
availableThreads = runtime.availableProcessors();
}
this.maxNumberOfTasks = availableThreads;
this.estimatorList = new ArrayList<PhymlSingleModel>(maxNumberOfTasks);
this.threadPool = Executors.newFixedThreadPool(maxNumberOfTasks);
}
/**
* Executes the model optimization
*
* @param estimator the model estimator to execute
*
* @return if succesfully added the task
*/
public boolean execute(PhymlSingleModel estimator) {
estimator.addObserver(this);
boolean added = estimatorList.add(estimator);
c.add(Executors.callable(estimator));
threadPool.execute(estimator);
return added;
}
protected void notifyObservers(int type, int value, Model model,
String message) {
setChanged();
notifyObservers(new ProgressInfo(type, value, model, message));
}
@Override
public void update(Observable o, Object arg) {
setChanged();
notifyObservers(arg);
}
/**
* Checks if exist more tasks in the task queue
*
* @return true, if exist more tasks to execute
*/
public boolean hasMoreTasks() {
for (PhymlSingleModel estimator : estimatorList) {
if (estimator.getModel().getTree() == null) {
return true;
}
}
return false;
}
}