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 java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.Hashtable;
28 import java.util.List;
32 import jalview.api.AlignCalcManagerI;
33 import jalview.api.AlignCalcWorkerI;
34 import jalview.datamodel.AlignmentAnnotation;
36 public class AlignCalcManager implements AlignCalcManagerI
39 * list of registered workers
41 private volatile List<AlignCalcWorkerI> restartable;
44 * types of worker _not_ to run (for example, because they have
45 * previously thrown errors)
47 private volatile List<Class<? extends AlignCalcWorkerI>> blackList;
50 * global record of calculations in progress
52 private volatile List<AlignCalcWorkerI> inProgress;
55 * record of calculations pending or in progress in the current context
57 private volatile Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating;
60 * workers that have run to completion so are candidates for visual-only
61 * update of their results
63 private HashSet<AlignCalcWorkerI> canUpdate;
68 public AlignCalcManager()
70 restartable = Collections
71 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
72 blackList = Collections.synchronizedList(
73 new ArrayList<Class<? extends AlignCalcWorkerI>>());
74 inProgress = Collections
75 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
76 updating = Collections.synchronizedMap(
77 new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
78 canUpdate = new HashSet<AlignCalcWorkerI>();
82 public void notifyStart(AlignCalcWorkerI worker)
84 synchronized (updating)
86 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
89 updating.put(worker.getClass(), upd = Collections
90 .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
102 * @see jalview.api.AlignCalcManagerI#isPending(jalview.api.AlignCalcWorkerI)
105 public boolean isPending(AlignCalcWorkerI workingClass)
107 List<AlignCalcWorkerI> upd;
108 synchronized (updating)
110 upd = updating.get(workingClass.getClass());
127 public boolean notifyWorking(AlignCalcWorkerI worker)
129 synchronized (inProgress)
131 if (inProgress.contains(worker))
133 return false; // worker is already working, so ask caller to wait around
137 inProgress.add(worker);
144 public void workerComplete(AlignCalcWorkerI worker)
146 synchronized (inProgress)
148 // jalview.bin.Console.errPrintln("Worker " + worker + " marked as
150 inProgress.remove(worker);
151 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
158 canUpdate.add(worker);
164 public void disableWorker(AlignCalcWorkerI worker)
166 synchronized (blackList)
168 blackList.add(worker.getClass());
173 public boolean isDisabled(AlignCalcWorkerI worker)
175 synchronized (blackList)
177 return blackList.contains(worker.getClass());
182 public void startWorker(AlignCalcWorkerI worker)
184 if (!isDisabled(worker))
186 Thread tw = new Thread(worker);
187 tw.setName(worker.getClass().toString());
193 public boolean isWorking(AlignCalcWorkerI worker)
195 synchronized (inProgress)
196 {// jalview.bin.Console.errPrintln("isWorking : worker "+(worker!=null ?
197 // worker.getClass():"null")+ " "+hashCode());
198 return worker != null && inProgress.contains(worker);
203 public boolean isWorking()
205 boolean working = false;
206 synchronized (inProgress)
208 // jalview.bin.Console.errPrintln("isWorking "+hashCode());
209 working |= inProgress.size() > 0;
211 synchronized (updating)
213 Collection<List<AlignCalcWorkerI>> workersLists = updating.values();
214 synchronized (workersLists)
216 for (List<AlignCalcWorkerI> workers : workersLists)
220 synchronized (workers)
222 working |= workers.size() > 0;
232 public void registerWorker(AlignCalcWorkerI worker)
234 synchronized (restartable)
236 if (!restartable.contains(worker))
238 restartable.add(worker);
245 public void restartWorkers()
247 synchronized (restartable)
249 for (AlignCalcWorkerI worker : restartable)
257 public boolean workingInvolvedWith(
258 AlignmentAnnotation alignmentAnnotation)
260 synchronized (inProgress)
262 for (AlignCalcWorkerI worker : inProgress)
264 if (worker.involves(alignmentAnnotation))
270 synchronized (updating)
272 for (List<AlignCalcWorkerI> workers : updating.values())
274 for (AlignCalcWorkerI worker : workers)
276 if (worker.involves(alignmentAnnotation))
287 public void updateAnnotationFor(
288 Class<? extends AlignCalcWorkerI> workerClass)
291 AlignCalcWorkerI[] workers;
292 synchronized (canUpdate)
294 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
296 for (AlignCalcWorkerI worker : workers)
298 if (workerClass.equals(worker.getClass()))
300 worker.updateAnnotation();
306 public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
307 Class<? extends AlignCalcWorkerI> workerClass)
309 List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
310 AlignCalcWorkerI[] workers;
311 synchronized (canUpdate)
313 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
315 for (AlignCalcWorkerI worker : workers)
317 if (workerClass.equals(worker.getClass()))
319 workingClass.add(worker);
322 return (workingClass.size() == 0) ? null : workingClass;
326 public void enableWorker(AlignCalcWorkerI worker)
328 synchronized (blackList)
330 blackList.remove(worker.getClass());
335 public void removeRegisteredWorkersOfClass(
336 Class<? extends AlignCalcWorkerI> typeToRemove)
338 List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
339 Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
340 synchronized (restartable)
342 for (AlignCalcWorkerI worker : restartable)
344 if (typeToRemove.equals(worker.getClass()))
346 removable.add(worker);
347 toremovannot.add(worker);
350 restartable.removeAll(removable);
352 synchronized (canUpdate)
354 for (AlignCalcWorkerI worker : canUpdate)
356 if (typeToRemove.equals(worker.getClass()))
358 removable.add(worker);
359 toremovannot.add(worker);
362 canUpdate.removeAll(removable);
364 // TODO: finish testing this extension
367 * synchronized (inProgress) { // need to kill or mark as dead any running
368 * threads... (inProgress.get(typeToRemove)); }
370 * if (workers == null) { return; } for (AlignCalcWorkerI worker : workers)
373 * if (isPending(worker)) { worker.abortAndDestroy(); startWorker(worker); }
374 * else { jalview.bin.Console.errPrintln("Pending exists for " + workerClass); } }
379 * Deletes the worker that update the given annotation, provided it is marked
383 public void removeWorkerForAnnotation(AlignmentAnnotation ann)
386 * first just find those to remove (to avoid
387 * ConcurrentModificationException)
389 List<AlignCalcWorkerI> toRemove = new ArrayList<AlignCalcWorkerI>();
390 for (AlignCalcWorkerI worker : restartable)
392 if (worker.involves(ann))
394 if (worker.isDeletable())
396 toRemove.add(worker);
402 * remove all references to deleted workers so any references
403 * they hold to annotation data can be garbage collected
405 for (AlignCalcWorkerI worker : toRemove)
407 restartable.remove(worker);
408 blackList.remove(worker.getClass());
409 inProgress.remove(worker);
410 canUpdate.remove(worker);
411 synchronized (updating)
413 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());