/*******************************************************************************\r
* Copyright (c) 2012 Ericsson\r
- * \r
+ *\r
* All rights reserved. This program and the accompanying materials are\r
* made available under the terms of the Eclipse Public License v1.0 which\r
* accompanies this distribution, and is available at\r
* http://www.eclipse.org/legal/epl-v10.html\r
- * \r
+ *\r
* Contributors:\r
* Patrick Tasse - Initial API and implementation\r
*******************************************************************************/\r
import org.eclipse.linuxtools.tmf.core.signal.TmfStateSystemBuildCompleted;\r
import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;\r
import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier;\r
+import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier2;\r
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;\r
import org.eclipse.linuxtools.tmf.ui.views.TmfView;\r
import org.eclipse.swt.widgets.TreeColumn;\r
import org.eclipse.ui.IActionBars;\r
\r
+/**\r
+ * The Control Flow view main object\r
+ *\r
+ */\r
public class ControlFlowView extends TmfView {\r
\r
// ------------------------------------------------------------------------\r
TRACE_COLUMN\r
};\r
\r
+ /**\r
+ * Redraw state enum\r
+ */\r
+ private enum State { IDLE, BUSY, PENDING }\r
+\r
// ------------------------------------------------------------------------\r
// Fields\r
// ------------------------------------------------------------------------\r
// The timegraph entry list\r
private ArrayList<ControlFlowEntry> fEntryList;\r
\r
+ // The time graph entry list synchronization object\r
+ final private Object fEntryListSyncObj = new Object();\r
+\r
// The start time\r
private long fStartTime;\r
\r
private long fEndTime;\r
\r
// The display width\r
- private int fDisplayWidth;\r
+ private final int fDisplayWidth;\r
\r
// The zoom thread\r
private ZoomThread fZoomThread;\r
\r
// The previous resource action\r
private Action fPreviousResourceAction;\r
- \r
+\r
// A comparator class\r
- private ControlFlowEntryComparator fControlFlowEntryComparator = new ControlFlowEntryComparator();\r
+ private final ControlFlowEntryComparator fControlFlowEntryComparator = new ControlFlowEntryComparator();\r
+\r
+ // The redraw state used to prevent unnecessary queuing of display runnables\r
+ private State fRedrawState = State.IDLE;\r
+\r
+ // The redraw synchronization object\r
+ final private Object fSyncObj = new Object();\r
\r
// ------------------------------------------------------------------------\r
// Classes\r
}\r
}\r
\r
- \r
+\r
private class ZoomThread extends Thread {\r
- private long fZoomStartTime;\r
- private long fZoomEndTime;\r
- private long fResolution;\r
- private IProgressMonitor fMonitor;\r
+ private final long fZoomStartTime;\r
+ private final long fZoomEndTime;\r
+ private final long fResolution;\r
+ private final IProgressMonitor fMonitor;\r
\r
public ZoomThread(long startTime, long endTime) {\r
super("ControlFlowView zoom"); //$NON-NLS-1$\r
\r
@Override\r
public void run() {\r
- ArrayList<ControlFlowEntry> entryList = fEntryList;\r
+ ArrayList<ControlFlowEntry> entryList = null;\r
+ synchronized (fEntryListSyncObj) {\r
+ entryList = fEntryList;\r
+ }\r
if (entryList == null) {\r
return;\r
}\r
}\r
zoom(entry, fMonitor);\r
}\r
- redraw();\r
}\r
\r
private void zoom(ControlFlowEntry entry, IProgressMonitor monitor) {\r
entry.setZoomedEventList(zoomedEventList);\r
}\r
}\r
+ redraw();\r
for (ControlFlowEntry child : entry.getChildren()) {\r
if (fMonitor.isCanceled()) {\r
return;\r
// Constructors\r
// ------------------------------------------------------------------------\r
\r
+ /**\r
+ * Constructor\r
+ */\r
public ControlFlowView() {\r
super(ID);\r
fDisplayWidth = Display.getDefault().getBounds().width;\r
// Signal handlers\r
// ------------------------------------------------------------------------\r
\r
+ /**\r
+ * Handler for the experiment selected signal\r
+ *\r
+ * @param signal\r
+ * The signal that's received\r
+ */\r
@TmfSignalHandler\r
public void experimentSelected(final TmfExperimentSelectedSignal<? extends ITmfEvent> signal) {\r
if (signal.getExperiment().equals(fSelectedExperiment)) {\r
thread.start();\r
}\r
\r
+ /**\r
+ * Handler for the synch signal\r
+ *\r
+ * @param signal\r
+ * The signal that's received\r
+ */\r
@TmfSignalHandler\r
public void synchToTime(final TmfTimeSynchSignal signal) {\r
- if (signal.getSource() == this) {\r
+ if (signal.getSource() == this || fSelectedExperiment == null || fSelectedExperiment.getTraces() == null) {\r
return;\r
}\r
final long time = signal.getCurrentTime().normalize(0, -9).getValue();\r
}\r
}\r
final int selectedThread = thread;\r
- \r
+\r
Display.getDefault().asyncExec(new Runnable() {\r
@Override\r
public void run() {\r
});\r
}\r
\r
+ /**\r
+ * Handler for the range sync signal\r
+ *\r
+ * @param signal\r
+ * The signal that's received\r
+ */\r
@TmfSignalHandler\r
public void synchToRange(final TmfRangeSynchSignal signal) {\r
- if (signal.getSource() == this) {\r
+ if (signal.getSource() == this || fSelectedExperiment == null) {\r
return;\r
}\r
final long startTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue();\r
});\r
}\r
\r
+ /**\r
+ * Handler for the state system build completed signal\r
+ *\r
+ * @param signal\r
+ * The signal that's received\r
+ */\r
@TmfSignalHandler\r
public void stateSystemBuildCompleted (final TmfStateSystemBuildCompleted signal) {\r
final TmfExperiment<?> selectedExperiment = fSelectedExperiment;\r
- if (selectedExperiment == null) {\r
+ if (selectedExperiment == null || selectedExperiment.getTraces() == null) {\r
return;\r
}\r
for (ITmfTrace<?> trace : selectedExperiment.getTraces()) {\r
buildTree(entryList, rootList);\r
}\r
Collections.sort(rootList, fControlFlowEntryComparator);\r
- fEntryList = rootList;\r
+ synchronized (fEntryListSyncObj) {\r
+ fEntryList = (ArrayList<ControlFlowEntry>) rootList.clone();\r
+ }\r
refresh(INITIAL_WINDOW_OFFSET);\r
}\r
for (ControlFlowEntry entry : rootList) {\r
}\r
}\r
\r
- private void buildTree(ArrayList<ControlFlowEntry> entryList, ArrayList<ControlFlowEntry> rootList) {\r
+ private static void buildTree(ArrayList<ControlFlowEntry> entryList,\r
+ ArrayList<ControlFlowEntry> rootList) {\r
for (ControlFlowEntry entry : entryList) {\r
boolean root = true;\r
if (entry.getParentThreadId() > 0) {\r
}\r
}\r
\r
- private List<ITimeEvent> getEventList(ControlFlowEntry entry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {\r
+ private static List<ITimeEvent> getEventList(ControlFlowEntry entry,\r
+ long startTime, long endTime, long resolution,\r
+ IProgressMonitor monitor) {\r
startTime = Math.max(startTime, entry.getStartTime());\r
endTime = Math.min(endTime, entry.getEndTime());\r
if (endTime <= startTime) {\r
return null;\r
}\r
- IStateSystemQuerier ssq = entry.getTrace().getStateSystem();\r
+ IStateSystemQuerier2 ssq = (IStateSystemQuerier2) entry.getTrace().getStateSystem();\r
List<ITimeEvent> eventList = null;\r
try {\r
int statusQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.STATUS);\r
- List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution);\r
+ List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution, monitor);\r
eventList = new ArrayList<ITimeEvent>(statusIntervals.size());\r
long lastEndTime = -1;\r
for (ITmfStateInterval statusInterval : statusIntervals) {\r
if (fTimeGraphCombo.isDisposed()) {\r
return;\r
}\r
- ITimeGraphEntry[] entries = fEntryList.toArray(new ITimeGraphEntry[0]);\r
+ ITimeGraphEntry[] entries = null;\r
+ synchronized (fEntryListSyncObj) {\r
+ entries = fEntryList.toArray(new ITimeGraphEntry[0]);\r
+ }\r
Arrays.sort(entries, fControlFlowEntryComparator);\r
fTimeGraphCombo.setInput(entries);\r
fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);\r
}\r
\r
private void redraw() {\r
+ synchronized (fSyncObj) {\r
+ if (fRedrawState == State.IDLE) {\r
+ fRedrawState = State.BUSY;\r
+ } else {\r
+ fRedrawState = State.PENDING;\r
+ return;\r
+ }\r
+ }\r
Display.getDefault().asyncExec(new Runnable() {\r
@Override\r
public void run() {\r
}\r
fTimeGraphCombo.redraw();\r
fTimeGraphCombo.update();\r
+ synchronized (fSyncObj) {\r
+ if (fRedrawState == State.PENDING) {\r
+ fRedrawState = State.IDLE;\r
+ redraw();\r
+ } else {\r
+ fRedrawState = State.IDLE;\r
+ }\r
+ }\r
}\r
});\r
}\r