critical path: bug 489360 Build the critical path in a separate thread
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Fri, 13 May 2016 18:39:28 +0000 (14:39 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Mon, 30 May 2016 14:05:40 +0000 (10:05 -0400)
The critical path content provider was waiting for the analysis to be completed
but this often happens in the main thread and the first time, it is the whole
graph that needs to be computed and that can block the main thread for a while.

This patch uses a separate build thread when the input is changed so it does
not block anymore.

Change-Id: I9cb99c0d93524961c5f8b45ada59d8a02db49bb0
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/72759
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
analysis/org.eclipse.tracecompass.analysis.graph.core/src/org/eclipse/tracecompass/analysis/graph/core/criticalpath/CriticalPathModule.java
analysis/org.eclipse.tracecompass.analysis.graph.ui/src/org/eclipse/tracecompass/internal/analysis/graph/ui/criticalpath/view/CriticalPathView.java

index 9b989ad9563d15720dfaf4792f63731cb8807303..30e9289afd17b36e97403f3160360af6793d7a40 100644 (file)
@@ -50,7 +50,7 @@ public class CriticalPathModule extends TmfAbstractAnalysisModule {
 
     private @Nullable TmfGraphBuilderModule fGraphModule;
 
-    private @Nullable TmfGraph fCriticalPath;
+    private volatile @Nullable TmfGraph fCriticalPath;
 
     /**
      * Default constructor
@@ -138,6 +138,7 @@ public class CriticalPathModule extends TmfAbstractAnalysisModule {
 
     @Override
     protected void parameterChanged(String name) {
+        fCriticalPath = null;
         cancel();
         resetAnalysis();
         schedule();
index e716284d5de6281f0764941be616dc2aedf6827c..1fab74e3e32850f1301989bdbede2e776dbd98b7 100644 (file)
@@ -17,8 +17,11 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jface.viewers.Viewer;
@@ -195,10 +198,48 @@ public class CriticalPathView extends AbstractTimeGraphView {
             }
         }
 
-        private Map<Object, Map<Object, CriticalPathEntry>> workerMaps = new HashMap<>();
-        private Map<Object, List<TimeGraphEntry>> workerEntries = new HashMap<>();
-        private Map<Object, List<ILinkEvent>> linkMap = new HashMap<>();
+        private class BuildThread extends Thread {
+            private final ITmfTrace fBuildTrace;
+            private final IProgressMonitor fMonitor;
+
+            public BuildThread(final ITmfTrace trace) {
+                super("Critical path view build"); //$NON-NLS-1$
+                fBuildTrace = trace;
+                fMonitor = new NullProgressMonitor();
+            }
+
+            @Override
+            public void run() {
+                try {
+                    CriticalPathModule module = Iterables.<@Nullable CriticalPathModule> getFirst(
+                            TmfTraceUtils.getAnalysisModulesOfClass(fBuildTrace, CriticalPathModule.class),
+                            null);
+                    if (module == null) {
+                        return;
+                    }
+                    module.schedule();
+                    if (module.waitForCompletion(fMonitor)) {
+                        refresh();
+                    }
+
+                } finally {
+                    fSyncLock.lock();
+                    fBuildThread = null;
+                    fSyncLock.unlock();
+                }
+            }
+
+            public void cancel() {
+                fMonitor.setCanceled(true);
+            }
+        }
+
+        private final Lock fSyncLock = new ReentrantLock();
+        private final Map<Object, Map<Object, CriticalPathEntry>> workerMaps = new HashMap<>();
+        private final Map<Object, List<TimeGraphEntry>> workerEntries = new HashMap<>();
+        private final Map<Object, List<ILinkEvent>> linkMap = new HashMap<>();
         private @Nullable Object fCurrentObject;
+        private @Nullable BuildThread fBuildThread = null;
 
         @Override
         public ITimeGraphEntry[] getElements(@Nullable Object inputElement) {
@@ -278,10 +319,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$
             }
 
-            module.schedule();
-            if (!module.waitForCompletion()) {
-                return null;
-            }
             final TmfGraph graph = module.getCriticalPath();
             return graph;
         }
@@ -339,11 +376,46 @@ public class CriticalPathView extends AbstractTimeGraphView {
 
         @Override
         public void dispose() {
-
+            fSyncLock.lock();
+            try {
+                BuildThread buildThread = fBuildThread;
+                if (buildThread != null) {
+                    buildThread.cancel();
+                }
+            } finally {
+                fSyncLock.unlock();
+            }
         }
 
         @Override
         public void inputChanged(@Nullable Viewer viewer, @Nullable Object oldInput, @Nullable Object newInput) {
+            // The input has changed, the critical path will be re-computed,
+            // wait for the analysis to be finished, then call the refresh
+            // method of the view
+            if (!(newInput instanceof List)) {
+                return;
+            }
+            List<?> list = (List<?>) newInput;
+            if (list.isEmpty()) {
+                return;
+            }
+            final ITmfTrace trace = getTrace();
+            if (trace == null) {
+                return;
+            }
+
+            fSyncLock.lock();
+            try {
+                BuildThread buildThread = fBuildThread;
+                if (buildThread != null) {
+                    buildThread.cancel();
+                }
+                buildThread = new BuildThread(trace);
+                buildThread.start();
+                fBuildThread = buildThread;
+            } finally {
+                fSyncLock.unlock();
+            }
         }
 
         @Override
This page took 0.026405 seconds and 5 git commands to generate.