critical path: bug 489360 Build the critical path in a separate thread
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.graph.ui / src / org / eclipse / tracecompass / internal / analysis / graph / ui / criticalpath / view / CriticalPathView.java
index 8af721017e92798df8b7f13c4f325b3bdf02e5e4..1fab74e3e32850f1301989bdbede2e776dbd98b7 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 École Polytechnique de Montréal
+ * Copyright (c) 2015, 2016 École Polytechnique de Montréal
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -15,9 +15,10 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
-import java.util.Iterator;
 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;
@@ -82,9 +83,9 @@ public class CriticalPathView extends AbstractTimeGraphView {
             COLUMN_PROCESS
     };
 
-    private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = NonNullUtils.checkNotNull(HashBasedTable.create());
+    private final Table<ITmfTrace, Object, List<ILinkEvent>> fLinks = HashBasedTable.create();
     /** The trace to entry list hash map */
-    private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = NonNullUtils.checkNotNull(HashBasedTable.create());
+    private final Table<ITmfTrace, Object, TmfGraphStatistics> fObjectStatistics = HashBasedTable.create();
 
     private final CriticalPathContentProvider fContentProvider = new CriticalPathContentProvider();
 
@@ -154,7 +155,7 @@ public class CriticalPathView extends AbstractTimeGraphView {
             public void visit(TmfEdge link, boolean horizontal) {
                 if (horizontal) {
                     Object parent = fGraph.getParentOf(link.getVertexFrom());
-                    CriticalPathEntry entry = checkNotNull(fRootList.get(parent));
+                    CriticalPathEntry entry = fRootList.get(parent);
                     TimeEvent ev = new TimeEvent(entry, link.getVertexFrom().getTs(), link.getDuration(),
                             getMatchingState(link.getType()).ordinal());
                     entry.addEvent(ev);
@@ -197,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) {
@@ -269,9 +308,6 @@ public class CriticalPathView extends AbstractTimeGraphView {
                 list.add(defaultParent);
             }
 
-            for (TimeGraphEntry entry : list) {
-                buildStatusEvents(trace, (CriticalPathEntry) NonNullUtils.checkNotNull(entry));
-            }
             workerEntries.put(worker, list);
         }
 
@@ -280,13 +316,9 @@ public class CriticalPathView extends AbstractTimeGraphView {
                     TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class),
                     null);
             if (module == null) {
-                throw new IllegalStateException();
+                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;
         }
@@ -311,7 +343,7 @@ public class CriticalPathView extends AbstractTimeGraphView {
             CriticalPathModule module = Iterables.<@Nullable CriticalPathModule> getFirst(
                     TmfTraceUtils.getAnalysisModulesOfClass(trace, CriticalPathModule.class), null);
             if (module == null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("View requires an analysis module"); //$NON-NLS-1$
             }
 
             final TmfGraph graph = module.getCriticalPath();
@@ -344,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
@@ -472,24 +539,8 @@ public class CriticalPathView extends AbstractTimeGraphView {
         return state;
     }
 
-    private void buildStatusEvents(ITmfTrace trace, CriticalPathEntry entry) {
-
-        long start = trace.getStartTime().getValue();
-        long end = trace.getEndTime().getValue() + 1;
-        long resolution = Math.max(1, (end - start) / getDisplayWidth());
-        List<ITimeEvent> eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, new NullProgressMonitor());
-
-        entry.setZoomedEventList(eventList);
-
-        redraw();
-
-        for (ITimeGraphEntry child : entry.getChildren()) {
-            buildStatusEvents(trace, (CriticalPathEntry) child);
-        }
-    }
-
     @Override
-    protected void buildEventList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor) {
+    protected void buildEntryList(@NonNull ITmfTrace trace, @NonNull ITmfTrace parentTrace, @NonNull IProgressMonitor monitor) {
         /* This class uses a content provider instead */
     }
 
@@ -497,31 +548,11 @@ public class CriticalPathView extends AbstractTimeGraphView {
     protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry entry,
             long startTime, long endTime, long resolution,
             IProgressMonitor monitor) {
-
-        final long realStart = Math.max(startTime, entry.getStartTime());
-        final long realEnd = Math.min(endTime, entry.getEndTime());
-        if (realEnd <= realStart) {
-            return null;
-        }
-        List<ITimeEvent> eventList = null;
-        entry.setZoomedEventList(null);
-        Iterator<ITimeEvent> iterator = entry.getTimeEventsIterator();
-        eventList = new ArrayList<>();
-
-        while (iterator.hasNext()) {
-            ITimeEvent event = iterator.next();
-            /* is event visible */
-            if (intersects(realStart, realEnd, NonNullUtils.checkNotNull(event))) {
-                eventList.add(event);
-            }
-        }
-        return eventList;
-    }
-
-    private static boolean intersects(final long realStart, final long realEnd, ITimeEvent event) {
-        return ((event.getTime() >= realStart) && (event.getTime() <= realEnd)) ||
-                ((event.getTime() + event.getDuration() > realStart) &&
-                        (event.getTime() + event.getDuration() < realEnd));
+        /*
+         * The event list is built in the HorizontalLinksVisitor. This is called
+         * only from the zoom thread and only for the CriticalPathBaseEntry.
+         */
+        return null;
     }
 
     @Override
This page took 0.028356 seconds and 5 git commands to generate.