2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.workers;
23 import jalview.api.AlignCalcManagerI;
24 import jalview.api.AlignCalcWorkerI;
25 import jalview.datamodel.AlignmentAnnotation;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.Hashtable;
31 import java.util.List;
35 public class AlignCalcManager implements AlignCalcManagerI
37 private volatile List<AlignCalcWorkerI> restartable = Collections
38 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
40 private volatile List<Class> blackList = Collections
41 .synchronizedList(new ArrayList<Class>());
44 * global record of calculations in progress
46 private volatile Map<Class, AlignCalcWorkerI> inProgress = Collections
47 .synchronizedMap(new Hashtable<Class, AlignCalcWorkerI>());
50 * record of calculations pending or in progress in the current context
52 private volatile Map<Class, List<AlignCalcWorkerI>> updating = Collections
53 .synchronizedMap(new Hashtable<Class, List<AlignCalcWorkerI>>());
56 public void notifyStart(AlignCalcWorkerI worker)
58 synchronized (updating)
60 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
66 .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
76 public boolean alreadyDoing(AlignCalcWorkerI worker)
78 synchronized (inProgress)
80 return inProgress.containsKey(worker.getClass());
87 * @see jalview.api.AlignCalcManagerI#isPending(jalview.api.AlignCalcWorkerI)
90 public boolean isPending(AlignCalcWorkerI workingClass)
92 List<AlignCalcWorkerI> upd;
93 synchronized (updating)
95 upd = updating.get(workingClass.getClass());
111 // TODO make into api method if needed ?
112 public int numberLive(AlignCalcWorkerI worker)
114 synchronized (updating)
116 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
127 public boolean notifyWorking(AlignCalcWorkerI worker)
129 synchronized (inProgress)
131 // TODO: decide if we should throw exceptions here if multiple workers
133 if (inProgress.get(worker.getClass()) != null)
138 .println("Warning: Multiple workers are running of type "
139 + worker.getClass());
143 inProgress.put(worker.getClass(), worker);
148 private final HashSet<AlignCalcWorkerI> canUpdate = new HashSet<AlignCalcWorkerI>();
151 public void workerComplete(AlignCalcWorkerI worker)
153 synchronized (inProgress)
155 // System.err.println("Worker "+worker.getClass()+" marked as complete.");
156 inProgress.remove(worker.getClass());
157 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
164 canUpdate.add(worker);
170 public void workerCannotRun(AlignCalcWorkerI worker)
172 synchronized (blackList)
174 blackList.add(worker.getClass());
178 public boolean isBlackListed(Class workerType)
180 synchronized (blackList)
182 return blackList.contains(workerType);
187 public void startWorker(AlignCalcWorkerI worker)
189 // System.err.println("Starting "+worker.getClass());
190 // new Exception("").printStackTrace();
192 Thread workerAsThread = (Thread) worker;
193 if (workerAsThread.isAlive()) {
194 workerAsThread.interrupt();
195 worker = worker.getNewWorker();
197 worker.setName(worker.getClass().getName());
202 public boolean isWorking(AlignCalcWorkerI worker)
204 synchronized (inProgress)
205 {// System.err.println("isWorking : worker "+(worker!=null ?
206 // worker.getClass():"null")+ " "+hashCode());
207 return worker != null && inProgress.get(worker.getClass()) == worker;
212 public boolean isWorking()
214 synchronized (inProgress)
216 // System.err.println("isWorking "+hashCode());
217 return inProgress.size() > 0;
222 public void registerWorker(AlignCalcWorkerI worker)
224 synchronized (restartable)
226 if (!restartable.contains(worker))
228 restartable.add(worker);
235 public void restartWorkers()
237 synchronized (restartable)
239 for (AlignCalcWorkerI worker : restartable)
247 public boolean workingInvolvedWith(AlignmentAnnotation alignmentAnnotation)
249 synchronized (inProgress)
251 for (AlignCalcWorkerI worker : inProgress.values())
253 if (worker.involves(alignmentAnnotation))
259 synchronized (updating)
261 for (List<AlignCalcWorkerI> workers : updating.values())
263 for (AlignCalcWorkerI worker : workers)
265 if (worker.involves(alignmentAnnotation))
276 public void updateAnnotationFor(Class workerClass)
279 AlignCalcWorkerI[] workers;
280 synchronized (canUpdate)
282 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
284 for (AlignCalcWorkerI worker : workers)
286 if (workerClass.equals(worker.getClass()))
288 worker.updateAnnotation();
294 public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
297 List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
298 AlignCalcWorkerI[] workers;
299 synchronized (canUpdate)
301 workers = canUpdate.toArray(new AlignCalcWorkerI[canUpdate.size()]);
303 for (AlignCalcWorkerI worker : workers)
305 if (workerClass.equals(worker.getClass()))
307 workingClass.add(worker);
310 return (workingClass.size() == 0) ? null : workingClass;
314 public boolean startRegisteredWorkersOfClass(Class workerClass)
316 List<AlignCalcWorkerI> workers = getRegisteredWorkersOfClass(workerClass);
321 for (AlignCalcWorkerI worker : workers)
323 if (!isPending(worker))
329 System.err.println("Pending exists for " + workerClass);
336 public void workerMayRun(AlignCalcWorkerI worker)
338 synchronized (blackList)
340 if (blackList.contains(worker.getClass()))
342 blackList.remove(worker.getClass());
348 public void removeRegisteredWorkersOfClass(Class typeToRemove)
350 List<AlignCalcWorkerI> workers = getRegisteredWorkersOfClass(typeToRemove);
351 List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
352 Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
353 synchronized (restartable)
355 for (AlignCalcWorkerI worker : restartable)
357 if (typeToRemove.equals(worker.getClass()))
359 removable.add(worker);
360 toremovannot.add(worker);
363 restartable.removeAll(removable);
365 synchronized (canUpdate)
367 for (AlignCalcWorkerI worker : canUpdate)
369 if (typeToRemove.equals(worker.getClass()))
371 removable.add(worker);
372 toremovannot.add(worker);
375 canUpdate.removeAll(removable);
377 // TODO: finish testing this extension
380 * synchronized (inProgress) { // need to kill or mark as dead any running
381 * threads... (inProgress.get(typeToRemove)); }
383 * if (workers == null) { return; } for (AlignCalcWorkerI worker : workers)
386 * if (isPending(worker)) { worker.abortAndDestroy(); startWorker(worker); }
387 * else { System.err.println("Pending exists for " + workerClass); } }