2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
18 package jalview.workers;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashSet;
23 import java.util.Hashtable;
24 import java.util.List;
28 import jalview.api.AlignCalcManagerI;
29 import jalview.api.AlignCalcWorkerI;
30 import jalview.datamodel.AlignmentAnnotation;
32 public class AlignCalcManager implements AlignCalcManagerI
34 private volatile List<AlignCalcWorkerI> restartable = Collections
35 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
37 private volatile List<Class> blackList = Collections
38 .synchronizedList(new ArrayList<Class>());
41 * global record of calculations in progress
43 private volatile Map<Class, AlignCalcWorkerI> inProgress = Collections
44 .synchronizedMap(new Hashtable<Class, AlignCalcWorkerI>());
47 * record of calculations pending or in progress in the current context
49 private volatile Map<Class, List<AlignCalcWorkerI>> updating = Collections
50 .synchronizedMap(new Hashtable<Class, List<AlignCalcWorkerI>>());
53 public void notifyStart(AlignCalcWorkerI worker)
55 synchronized (updating)
57 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
63 .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
73 public boolean alreadyDoing(AlignCalcWorkerI worker)
75 synchronized (inProgress)
77 return inProgress.containsKey(worker.getClass());
84 * @see jalview.api.AlignCalcManagerI#isPending(jalview.api.AlignCalcWorkerI)
87 public boolean isPending(AlignCalcWorkerI workingClass)
89 List<AlignCalcWorkerI> upd;
90 synchronized (updating)
92 upd = updating.get(workingClass.getClass());
108 // TODO make into api method if needed ?
109 public int numberLive(AlignCalcWorkerI worker)
111 synchronized (updating)
113 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
124 public boolean notifyWorking(AlignCalcWorkerI worker)
126 synchronized (inProgress)
128 // TODO: decide if we should throw exceptions here if multiple workers
130 if (inProgress.get(worker.getClass()) != null)
135 .println("Warning: Multiple workers are running of type "
136 + worker.getClass());
140 inProgress.put(worker.getClass(), worker);
145 private final HashSet<AlignCalcWorkerI> canUpdate = new HashSet<AlignCalcWorkerI>();
148 public void workerComplete(AlignCalcWorkerI worker)
150 synchronized (inProgress)
152 // System.err.println("Worker "+worker.getClass()+" marked as complete.");
153 inProgress.remove(worker.getClass());
154 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
161 canUpdate.add(worker);
167 public void workerCannotRun(AlignCalcWorkerI worker)
169 synchronized (blackList)
171 blackList.add(worker.getClass());
175 public boolean isBlackListed(Class workerType)
177 synchronized (blackList)
179 return blackList.contains(workerType);
184 public void startWorker(AlignCalcWorkerI worker)
186 // System.err.println("Starting "+worker.getClass());
187 // new Exception("").printStackTrace();
188 Thread tw = new Thread(worker);
189 tw.setName(worker.getClass().toString());
194 public boolean isWorking(AlignCalcWorkerI worker)
196 synchronized (inProgress)
197 {// System.err.println("isWorking : worker "+(worker!=null ?
198 // worker.getClass():"null")+ " "+hashCode());
199 return worker != null && inProgress.get(worker.getClass()) == worker;
204 public boolean isWorking()
206 synchronized (inProgress)
208 // System.err.println("isWorking "+hashCode());
209 return inProgress.size() > 0;
214 public void registerWorker(AlignCalcWorkerI worker)
216 synchronized (restartable)
218 if (!restartable.contains(worker))
220 restartable.add(worker);
227 public void restartWorkers()
229 synchronized (restartable)
231 for (AlignCalcWorkerI worker : restartable)
239 public boolean workingInvolvedWith(AlignmentAnnotation alignmentAnnotation)
241 synchronized (inProgress)
243 for (AlignCalcWorkerI worker : inProgress.values())
245 if (worker.involves(alignmentAnnotation))
251 synchronized (updating)
253 for (List<AlignCalcWorkerI> workers : updating.values())
255 for (AlignCalcWorkerI worker : workers)
256 if (worker.involves(alignmentAnnotation))
266 public void updateAnnotationFor(Class workerClass)
269 AlignCalcWorkerI[] workers;
270 synchronized (canUpdate)
272 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
274 for (AlignCalcWorkerI worker : workers)
276 if (workerClass.equals(worker.getClass()))
278 worker.updateAnnotation();
284 public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
287 List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
288 AlignCalcWorkerI[] workers;
289 synchronized (canUpdate)
291 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
293 for (AlignCalcWorkerI worker : workers)
295 if (workerClass.equals(worker.getClass()))
297 workingClass.add(worker);
300 return (workingClass.size() == 0) ? null : workingClass;
304 public boolean startRegisteredWorkersOfClass(Class workerClass)
306 List<AlignCalcWorkerI> workers = getRegisteredWorkersOfClass(workerClass);
311 for (AlignCalcWorkerI worker : workers)
313 if (!isPending(worker))
319 System.err.println("Pending exists for " + workerClass);
326 public void workerMayRun(AlignCalcWorkerI worker)
328 synchronized (blackList)
330 if (blackList.contains(worker.getClass()))
332 blackList.remove(worker.getClass());
338 public void removeRegisteredWorkersOfClass(Class typeToRemove)
340 List<AlignCalcWorkerI> workers = getRegisteredWorkersOfClass(typeToRemove);
341 List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
342 Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
343 synchronized (restartable)
345 for (AlignCalcWorkerI worker : restartable)
347 if (typeToRemove.equals(worker.getClass()))
349 removable.add(worker);
350 toremovannot.add(worker);
353 restartable.removeAll(removable);
355 synchronized (canUpdate)
357 for (AlignCalcWorkerI worker : canUpdate)
359 if (typeToRemove.equals(worker.getClass()))
361 removable.add(worker);
362 toremovannot.add(worker);
365 canUpdate.removeAll(removable);
367 // TODO: finish testing this extension
370 * synchronized (inProgress) { // need to kill or mark as dead any running
371 * threads... (inProgress.get(typeToRemove)); }
373 * if (workers == null) { return; } for (AlignCalcWorkerI worker : workers)
376 * if (isPending(worker)) { worker.abortAndDestroy(); startWorker(worker); }
377 * else { System.err.println("Pending exists for " + workerClass); } }