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
38 * list of registered workers
40 private volatile List<AlignCalcWorkerI> restartable;
43 * types of worker _not_ to run (for example, because they have
44 * previously thrown errors)
46 private volatile List<Class<? extends AlignCalcWorkerI>> blackList;
49 * global record of calculations in progress
51 private volatile List<AlignCalcWorkerI> inProgress;
54 * record of calculations pending or in progress in the current context
56 private volatile Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating;
59 * workers that have run to completion so are candidates for visual-only
60 * update of their results
62 private HashSet<AlignCalcWorkerI> canUpdate;
67 public AlignCalcManager()
69 restartable = Collections
70 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
71 blackList = Collections.synchronizedList(
72 new ArrayList<Class<? extends AlignCalcWorkerI>>());
73 inProgress = Collections
74 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
75 updating = Collections.synchronizedMap(
76 new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
77 canUpdate = new HashSet<AlignCalcWorkerI>();
81 public void notifyStart(AlignCalcWorkerI worker)
83 synchronized (updating)
85 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
88 updating.put(worker.getClass(), upd = Collections
89 .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
101 * @see jalview.api.AlignCalcManagerI#isPending(jalview.api.AlignCalcWorkerI)
104 public boolean isPending(AlignCalcWorkerI workingClass)
106 List<AlignCalcWorkerI> upd;
107 synchronized (updating)
109 upd = updating.get(workingClass.getClass());
126 public boolean notifyWorking(AlignCalcWorkerI worker)
128 synchronized (inProgress)
130 if (inProgress.contains(worker))
132 return false; // worker is already working, so ask caller to wait around
136 inProgress.add(worker);
143 public void workerComplete(AlignCalcWorkerI worker)
145 synchronized (inProgress)
147 // System.err.println("Worker " + worker + " marked as complete.");
148 inProgress.remove(worker);
149 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
156 canUpdate.add(worker);
162 public void disableWorker(AlignCalcWorkerI worker)
164 synchronized (blackList)
166 blackList.add(worker.getClass());
171 public boolean isDisabled(AlignCalcWorkerI worker)
173 synchronized (blackList)
175 return blackList.contains(worker.getClass());
180 public void startWorker(AlignCalcWorkerI worker)
182 if (!isDisabled(worker))
184 Thread tw = new Thread(worker);
185 tw.setName(worker.getClass().toString());
191 public boolean isWorking(AlignCalcWorkerI worker)
193 synchronized (inProgress)
194 {// System.err.println("isWorking : worker "+(worker!=null ?
195 // worker.getClass():"null")+ " "+hashCode());
196 return worker != null && inProgress.contains(worker);
201 public boolean isWorking()
203 boolean working=false;
204 synchronized (inProgress)
206 // System.err.println("isWorking "+hashCode());
207 working |= inProgress.size() > 0;
209 synchronized (updating)
211 for (List<AlignCalcWorkerI> workers : updating.values())
213 working |= workers.size() > 0;
220 public void registerWorker(AlignCalcWorkerI worker)
222 synchronized (restartable)
224 if (!restartable.contains(worker))
226 restartable.add(worker);
233 public void restartWorkers()
235 synchronized (restartable)
237 for (AlignCalcWorkerI worker : restartable)
245 public boolean workingInvolvedWith(
246 AlignmentAnnotation alignmentAnnotation)
248 synchronized (inProgress)
250 for (AlignCalcWorkerI worker : inProgress)
252 if (worker.involves(alignmentAnnotation))
258 synchronized (updating)
260 for (List<AlignCalcWorkerI> workers : updating.values())
262 for (AlignCalcWorkerI worker : workers)
264 if (worker.involves(alignmentAnnotation))
275 public void updateAnnotationFor(
276 Class<? extends AlignCalcWorkerI> 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(
295 Class<? extends AlignCalcWorkerI> workerClass)
297 List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
298 synchronized (canUpdate)
300 for (AlignCalcWorkerI worker : canUpdate)
302 if (workerClass.equals(worker.getClass()))
304 workingClass.add(worker);
308 return (workingClass.size() == 0) ? null : workingClass;
312 public void enableWorker(AlignCalcWorkerI worker)
314 synchronized (blackList)
316 blackList.remove(worker.getClass());
321 public void removeRegisteredWorkersOfClass(
322 Class<? extends AlignCalcWorkerI> typeToRemove)
324 List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
325 Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
326 synchronized (restartable)
328 for (AlignCalcWorkerI worker : restartable)
330 if (typeToRemove.equals(worker.getClass()))
332 removable.add(worker);
333 toremovannot.add(worker);
336 restartable.removeAll(removable);
338 synchronized (canUpdate)
340 for (AlignCalcWorkerI worker : canUpdate)
342 if (typeToRemove.equals(worker.getClass()))
344 removable.add(worker);
345 toremovannot.add(worker);
348 canUpdate.removeAll(removable);
350 // TODO: finish testing this extension
353 * synchronized (inProgress) { // need to kill or mark as dead any running
354 * threads... (inProgress.get(typeToRemove)); }
356 * if (workers == null) { return; } for (AlignCalcWorkerI worker : workers)
359 * if (isPending(worker)) { worker.abortAndDestroy(); startWorker(worker); }
360 * else { System.err.println("Pending exists for " + workerClass); } }
365 * Deletes the worker that update the given annotation, provided it is marked
369 public void removeWorkerForAnnotation(AlignmentAnnotation ann)
372 * first just find those to remove (to avoid
373 * ConcurrentModificationException)
375 List<AlignCalcWorkerI> toRemove = new ArrayList<AlignCalcWorkerI>();
376 for (AlignCalcWorkerI worker : restartable)
378 if (worker.involves(ann))
380 if (worker.isDeletable())
382 toRemove.add(worker);
388 * remove all references to deleted workers so any references
389 * they hold to annotation data can be garbage collected
391 for (AlignCalcWorkerI worker : toRemove)
393 restartable.remove(worker);
394 blackList.remove(worker.getClass());
395 inProgress.remove(worker);
396 canUpdate.remove(worker);
397 synchronized (updating)
399 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());