JAL - 3690 AlignCalc rebuilt - FutureTask-based manager
[jalview.git] / src / jalview / workers / AlignCalcManager.java
index d52ffe5..79ca863 100644 (file)
@@ -22,10 +22,12 @@ package jalview.workers;
 
 import jalview.api.AlignCalcManagerI;
 import jalview.api.AlignCalcWorkerI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
@@ -37,62 +39,70 @@ public class AlignCalcManager implements AlignCalcManagerI
   /*
    * list of registered workers
    */
-  private volatile List<AlignCalcWorkerI> restartable;
+  private final List<AlignCalcWorkerI> restartable = Collections
+          .synchronizedList(new ArrayList<AlignCalcWorkerI>());
 
   /*
    * types of worker _not_ to run (for example, because they have
    * previously thrown errors)
    */
-  private volatile List<Class<? extends AlignCalcWorkerI>> blackList;
+  private final List<Class<? extends AlignCalcWorkerI>> blackList = Collections
+          .synchronizedList(new ArrayList<Class<? extends AlignCalcWorkerI>>());
 
   /*
    * global record of calculations in progress
    */
-  private volatile List<AlignCalcWorkerI> inProgress;
+  private final List<AlignCalcWorkerI> inProgress = Collections
+          .synchronizedList(new ArrayList<AlignCalcWorkerI>());
 
   /*
    * record of calculations pending or in progress in the current context
    */
-  private volatile Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating;
+  private final Map<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>> updating =
+          new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>();
 
   /*
    * workers that have run to completion so are candidates for visual-only 
    * update of their results
    */
-  private HashSet<AlignCalcWorkerI> canUpdate;
+  private HashSet<AlignCalcWorkerI> canUpdate = new HashSet<>();;
 
-  /**
-   * Constructor
-   */
-  public AlignCalcManager()
+  private static boolean listContains(List<AlignCalcWorkerI> upd,
+          AlignCalcWorkerI worker)
   {
-    restartable = Collections
-            .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-    blackList = Collections
-            .synchronizedList(new ArrayList<Class<? extends AlignCalcWorkerI>>());
-    inProgress = Collections
-            .synchronizedList(new ArrayList<AlignCalcWorkerI>());
-    updating = Collections
-            .synchronizedMap(new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
-    canUpdate = new HashSet<>();
+    // avoid use of 'Contains' in case
+    for (AlignCalcWorkerI _otherworker : upd)
+    {
+      if (_otherworker == upd)
+      {
+        return true;
+      }
+    }
+    return false;
   }
-
   @Override
-  public void notifyStart(AlignCalcWorkerI worker)
+  public void notifyStarted(AlignCalcWorkerI worker)
   {
     synchronized (updating)
     {
       List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
       if (upd == null)
       {
-        updating.put(
-                worker.getClass(),
-                upd = Collections
-                        .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
+        updating.put(worker.getClass(), upd = Collections
+                .synchronizedList(new ArrayList<AlignCalcWorkerI>()));
       }
       synchronized (upd)
       {
-        upd.add(worker);
+        if (listContains(upd, worker))
+        {
+          Cache.log.debug(
+                    "Ignoring second call to notifyStart for worker "
+                            + worker);
+        }
+        else
+        {
+          upd.add(worker);
+        }
       }
     }
   }
@@ -105,22 +115,10 @@ public class AlignCalcManager implements AlignCalcManagerI
   @Override
   public boolean isPending(AlignCalcWorkerI workingClass)
   {
-    List<AlignCalcWorkerI> upd;
     synchronized (updating)
     {
-      upd = updating.get(workingClass.getClass());
-      if (upd == null)
-      {
-        return false;
-      }
-      synchronized (upd)
-      {
-        if (upd.size() > 1)
-        {
-          return true;
-        }
-      }
-      return false;
+      List<AlignCalcWorkerI> upd = updating.get(workingClass.getClass());
+      return upd != null && upd.size() > 1;
     }
   }
 
@@ -129,7 +127,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   {
     synchronized (inProgress)
     {
-      if (inProgress.contains(worker))
+      if (listContains(inProgress, worker))
       {
         return false; // worker is already working, so ask caller to wait around
       }
@@ -146,7 +144,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   {
     synchronized (inProgress)
     {
-      // System.err.println("Worker " + worker + " marked as complete.");
+      Cache.log.debug("Worker " + worker + " marked as complete.");
       inProgress.remove(worker);
       List<AlignCalcWorkerI> upd = updating.get(worker.getClass());
       if (upd != null)
@@ -183,7 +181,15 @@ public class AlignCalcManager implements AlignCalcManagerI
   {
     if (!isDisabled(worker))
     {
-      Thread tw = new Thread(worker);
+      Thread tw = new Thread(() -> {
+        try
+        {
+          worker.run();
+        } catch (Exception e)
+        {
+          e.printStackTrace();
+        }
+      });
       tw.setName(worker.getClass().toString());
       tw.start();
     }
@@ -214,7 +220,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   {
     synchronized (restartable)
     {
-      if (!restartable.contains(worker))
+      if (!listContains(restartable, worker))
       {
         restartable.add(worker);
       }
@@ -235,7 +241,8 @@ public class AlignCalcManager implements AlignCalcManagerI
   }
 
   @Override
-  public boolean workingInvolvedWith(AlignmentAnnotation alignmentAnnotation)
+  public boolean workingInvolvedWith(
+          AlignmentAnnotation alignmentAnnotation)
   {
     synchronized (inProgress)
     {
@@ -310,7 +317,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   }
 
   @Override
-  public void removeRegisteredWorkersOfClass(
+  public void removeWorkersOfClass(
           Class<? extends AlignCalcWorkerI> typeToRemove)
   {
     List<AlignCalcWorkerI> removable = new ArrayList<>();