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.bin.Jalview;
26 import jalview.datamodel.AlignmentAnnotation;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.Hashtable;
32 import java.util.List;
36 public class AlignCalcManager implements AlignCalcManagerI
38 public static final String STARTED = "started";
40 public static final String FINISHED = "finished";
43 * list of registered workers
45 private volatile List<AlignCalcWorkerI> restartable;
48 * types of worker _not_ to run (for example, because they have
49 * previously thrown errors)
51 private volatile List<Class<? extends AlignCalcWorkerI>> blackList;
54 * global record of calculations in progress
56 private volatile List<AlignCalcWorkerI> inProgress;
59 * record of calculations pending or in progress in the current context
61 private volatile Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating;
64 * workers that have run to completion so are candidates for visual-only
65 * update of their results
67 private HashSet<AlignCalcWorkerI> canUpdate;
72 public AlignCalcManager()
74 restartable = Collections
75 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
76 blackList = Collections.synchronizedList(
77 new ArrayList<Class<? extends AlignCalcWorkerI>>());
78 inProgress = Collections
79 .synchronizedList(new ArrayList<AlignCalcWorkerI>());
80 updating = Collections.synchronizedMap(
81 new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
82 canUpdate = new HashSet<>();
86 public void notifyStart(AlignCalcWorkerI worker)
88 synchronized (updating)
90 Jalview.getInstance().notifyWorker(worker, STARTED);
91 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
94 updating.put(worker.getClass(), upd = Collections
95 .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
107 * @see jalview.api.AlignCalcManagerI#isPending(jalview.api.AlignCalcWorkerI)
110 public boolean isPending(AlignCalcWorkerI workingClass)
112 List<AlignCalcWorkerI> upd;
113 synchronized (updating)
115 upd = updating.get(workingClass.getClass());
132 public boolean notifyWorking(AlignCalcWorkerI worker)
134 synchronized (inProgress)
136 if (inProgress.contains(worker))
138 return false; // worker is already working, so ask caller to wait around
142 inProgress.add(worker);
149 public void workerComplete(AlignCalcWorkerI worker)
151 synchronized (inProgress)
153 Jalview.getInstance().notifyWorker(worker, FINISHED);
154 // System.err.println("Worker " + worker + " marked as complete.");
155 inProgress.remove(worker);
156 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
163 canUpdate.add(worker);
169 public void disableWorker(AlignCalcWorkerI worker)
171 synchronized (blackList)
173 blackList.add(worker.getClass());
178 public boolean isDisabled(AlignCalcWorkerI worker)
180 synchronized (blackList)
182 return blackList.contains(worker.getClass());
187 public void startWorker(AlignCalcWorkerI worker)
189 if (!isDisabled(worker))
191 Thread tw = new Thread(worker);
192 tw.setName(worker.getClass().toString());
193 Jalview.execThread(tw); // JAL-3563
199 public boolean isWorking(AlignCalcWorkerI worker)
201 synchronized (inProgress)
202 {// System.err.println("isWorking : worker "+(worker!=null ?
203 // worker.getClass():"null")+ " "+hashCode());
204 return worker != null && inProgress.contains(worker);
209 public boolean isWorking()
211 synchronized (inProgress)
213 // System.err.println("isWorking "+hashCode());
214 return inProgress.size() > 0;
219 public void registerWorker(AlignCalcWorkerI worker)
221 synchronized (restartable)
223 if (!restartable.contains(worker))
225 restartable.add(worker);
232 public void restartWorkers()
234 synchronized (restartable)
236 for (AlignCalcWorkerI worker : restartable)
244 public boolean workingInvolvedWith(
245 AlignmentAnnotation alignmentAnnotation)
247 synchronized (inProgress)
249 for (AlignCalcWorkerI worker : inProgress)
251 if (worker.involves(alignmentAnnotation))
257 synchronized (updating)
259 for (List<AlignCalcWorkerI> workers : updating.values())
261 for (AlignCalcWorkerI worker : workers)
263 if (worker.involves(alignmentAnnotation))
274 public void updateAnnotationFor(
275 Class<? extends AlignCalcWorkerI> workerClass)
278 AlignCalcWorkerI[] workers;
279 synchronized (canUpdate)
281 workers = canUpdate.toArray(new AlignCalcWorkerI[0]);
283 for (AlignCalcWorkerI worker : workers)
285 if (workerClass.equals(worker.getClass()))
287 worker.updateAnnotation();
293 public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
294 Class<? extends AlignCalcWorkerI> workerClass)
296 List<AlignCalcWorkerI> workingClass = new ArrayList<>();
297 synchronized (canUpdate)
299 for (AlignCalcWorkerI worker : canUpdate)
301 if (workerClass.equals(worker.getClass()))
303 workingClass.add(worker);
307 return (workingClass.size() == 0) ? null : workingClass;
311 public void enableWorker(AlignCalcWorkerI worker)
313 synchronized (blackList)
315 blackList.remove(worker.getClass());
320 public void removeRegisteredWorkersOfClass(
321 Class<? extends AlignCalcWorkerI> typeToRemove)
323 List<AlignCalcWorkerI> removable = new ArrayList<>();
324 Set<AlignCalcWorkerI> toremovannot = new HashSet<>();
325 synchronized (restartable)
327 for (AlignCalcWorkerI worker : restartable)
329 if (typeToRemove.equals(worker.getClass()))
331 removable.add(worker);
332 toremovannot.add(worker);
335 restartable.removeAll(removable);
337 synchronized (canUpdate)
339 for (AlignCalcWorkerI worker : canUpdate)
341 if (typeToRemove.equals(worker.getClass()))
343 removable.add(worker);
344 toremovannot.add(worker);
347 canUpdate.removeAll(removable);
349 // TODO: finish testing this extension
352 * synchronized (inProgress) { // need to kill or mark as dead any running
353 * threads... (inProgress.get(typeToRemove)); }
355 * if (workers == null) { return; } for (AlignCalcWorkerI worker : workers)
358 * if (isPending(worker)) { worker.abortAndDestroy(); startWorker(worker); }
359 * else { System.err.println("Pending exists for " + workerClass); } }
364 * Deletes the worker that update the given annotation, provided it is marked
368 public void removeWorkerForAnnotation(AlignmentAnnotation ann)
371 * first just find those to remove (to avoid
372 * ConcurrentModificationException)
374 List<AlignCalcWorkerI> toRemove = new ArrayList<>();
375 for (AlignCalcWorkerI worker : restartable)
377 if (worker.involves(ann))
379 if (worker.isDeletable())
381 toRemove.add(worker);
387 * remove all references to deleted workers so any references
388 * they hold to annotation data can be garbage collected
390 for (AlignCalcWorkerI worker : toRemove)
392 restartable.remove(worker);
393 blackList.remove(worker.getClass());
394 inProgress.remove(worker);
395 canUpdate.remove(worker);
396 synchronized (updating)
398 List<AlignCalcWorkerI> upd = updating.get(worker.getClass());