mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
[202553] - [debug view][stack] Stack frames layout node retrieves all stack frames when stepping fast.
This commit is contained in:
parent
76b3eddc76
commit
152ee1c3f1
8 changed files with 393 additions and 165 deletions
|
@ -70,7 +70,10 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement
|
||||||
{
|
{
|
||||||
return IModelDelta.CONTENT;
|
return IModelDelta.CONTENT;
|
||||||
} else if (e instanceof IContainerSuspendedDMEvent) {
|
} else if (e instanceof IContainerSuspendedDMEvent) {
|
||||||
return IModelDelta.CONTENT;
|
// no change, update happens on FullStackRefreshEvent
|
||||||
|
return IModelDelta.NO_CHANGE;
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
|
return IModelDelta.CONTENT;
|
||||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||||
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
||||||
{
|
{
|
||||||
|
@ -93,7 +96,9 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement
|
||||||
{
|
{
|
||||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||||
} else if (e instanceof IContainerSuspendedDMEvent) {
|
} else if (e instanceof IContainerSuspendedDMEvent) {
|
||||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
// do nothing
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
|
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||||
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,6 +119,16 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode
|
||||||
// a delta for all the threads.
|
// a delta for all the threads.
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
|
return;
|
||||||
|
} else if (e instanceof FullStackRefreshEvent &&
|
||||||
|
((FullStackRefreshEvent)e).getDMContext() instanceof IContainerDMContext)
|
||||||
|
{
|
||||||
|
// The step sequence end event occured on a container and not on a thread. Do not
|
||||||
|
// return a context for this event, which will force the view model to generate
|
||||||
|
// a delta for all the threads.
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
} else if (e instanceof ModelProxyInstalledEvent) {
|
} else if (e instanceof ModelProxyInstalledEvent) {
|
||||||
getThreadVMCForModelProxyInstallEvent(
|
getThreadVMCForModelProxyInstallEvent(
|
||||||
parentDelta,
|
parentDelta,
|
||||||
|
@ -220,6 +230,9 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode
|
||||||
{
|
{
|
||||||
return IModelDelta.CONTENT;
|
return IModelDelta.CONTENT;
|
||||||
} else if (e instanceof ISuspendedDMEvent) {
|
} else if (e instanceof ISuspendedDMEvent) {
|
||||||
|
// no change, update happens on FullStackRefreshEvent
|
||||||
|
return IModelDelta.NO_CHANGE;
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
return IModelDelta.CONTENT;
|
return IModelDelta.CONTENT;
|
||||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||||
!(((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) )
|
!(((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) )
|
||||||
|
@ -244,6 +257,9 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode
|
||||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||||
rm.done();
|
rm.done();
|
||||||
} else if (e instanceof ISuspendedDMEvent) {
|
} else if (e instanceof ISuspendedDMEvent) {
|
||||||
|
// no change
|
||||||
|
rm.done();
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||||
rm.done();
|
rm.done();
|
||||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
|
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||||
|
import org.eclipse.dd.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
|
||||||
|
import org.eclipse.dd.dsf.ui.viewmodel.update.IElementUpdateTester;
|
||||||
|
import org.eclipse.jface.viewers.TreePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatic update strategy specialized for delayed full stack frame updates. The
|
||||||
|
* strategy can operate in lazy mode where only the top stack frame is
|
||||||
|
* invalidated, while in non-lazy mode everything is invalidated.
|
||||||
|
*/
|
||||||
|
public class DelayedStackRefreshUpdatePolicy extends AutomaticUpdatePolicy {
|
||||||
|
|
||||||
|
private static final class DelayedStackRefreshUpdateTester implements IElementUpdateTester {
|
||||||
|
|
||||||
|
private final boolean fLazyMode;
|
||||||
|
DelayedStackRefreshUpdateTester(boolean lazyMode) {
|
||||||
|
fLazyMode= lazyMode;
|
||||||
|
}
|
||||||
|
public int getUpdateFlags(Object viewerInput, TreePath path) {
|
||||||
|
if (fLazyMode) {
|
||||||
|
Object element = path.getSegmentCount() != 0 ? path.getLastSegment() : viewerInput;
|
||||||
|
if (element instanceof IDMVMContext) {
|
||||||
|
IDMContext dmc= ((IDMVMContext) element).getDMContext();
|
||||||
|
if (dmc instanceof IFrameDMContext) {
|
||||||
|
if (((IFrameDMContext) dmc).getLevel() > 0) {
|
||||||
|
// mark as dirty only
|
||||||
|
return DIRTY;
|
||||||
|
} else {
|
||||||
|
return FLUSH;
|
||||||
|
}
|
||||||
|
} else if (dmc instanceof IExecutionDMContext) {
|
||||||
|
return DIRTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean includes(IElementUpdateTester tester) {
|
||||||
|
// A non-lazy tester includes a lazy tester, but not vice versa.
|
||||||
|
// This allows entries that were marked as dirty by a flush with
|
||||||
|
// the lazy mode to be superceded by a non-lazy update which
|
||||||
|
// actually clears the entries that were marked as dirty.
|
||||||
|
if (tester instanceof DelayedStackRefreshUpdateTester) {
|
||||||
|
DelayedStackRefreshUpdateTester sfTester = (DelayedStackRefreshUpdateTester)tester;
|
||||||
|
if (fLazyMode) {
|
||||||
|
return sfTester.fLazyMode;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String DELAYED_UPDATE_POLICY_ID= "org.eclipse.dd.dsf.ui.viewmodel.update.lazyUpdatePolicy"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final DelayedStackRefreshUpdateTester fgLazyUpdateTester= new DelayedStackRefreshUpdateTester(true);
|
||||||
|
private static final DelayedStackRefreshUpdateTester fgNonLazyUpdateTester= new DelayedStackRefreshUpdateTester(false);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IElementUpdateTester getElementUpdateTester(Object event) {
|
||||||
|
if (event instanceof ISuspendedDMEvent) {
|
||||||
|
return fgLazyUpdateTester;
|
||||||
|
} else if (event instanceof FullStackRefreshEvent) {
|
||||||
|
return fgNonLazyUpdateTester;
|
||||||
|
} else {
|
||||||
|
return super.getElementUpdateTester(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy#getID()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getID() {
|
||||||
|
return DELAYED_UPDATE_POLICY_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy#getName()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Delayed Stack Refresh"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the end of a sequence of steps. Should be handled like a suspended
|
||||||
|
* event to trigger a full refresh of stack frames.
|
||||||
|
*/
|
||||||
|
public class FullStackRefreshEvent extends AbstractDMEvent<IExecutionDMContext> {
|
||||||
|
|
||||||
|
public FullStackRefreshEvent(IExecutionDMContext execCtx) {
|
||||||
|
super(execCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -45,7 +45,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRe
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
|
||||||
import org.eclipse.debug.ui.DebugUITools;
|
import org.eclipse.debug.ui.DebugUITools;
|
||||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||||
import org.eclipse.ui.IMemento;
|
import org.eclipse.ui.IMemento;
|
||||||
|
@ -114,6 +113,7 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update.getOffset() == 0 && update.getLength() == 1) {
|
if (update.getOffset() == 0 && update.getLength() == 1) {
|
||||||
|
// Requesting top stack frame only
|
||||||
stackService.getTopFrame(
|
stackService.getTopFrame(
|
||||||
execDmc,
|
execDmc,
|
||||||
new ViewerDataRequestMonitor<IFrameDMContext>(getSession().getExecutor(), update) {
|
new ViewerDataRequestMonitor<IFrameDMContext>(getSession().getExecutor(), update) {
|
||||||
|
@ -128,8 +128,8 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Requesting top stack frame only
|
|
||||||
} else {
|
} else {
|
||||||
|
// full stack dump
|
||||||
stackService.getFrames(
|
stackService.getFrames(
|
||||||
execDmc,
|
execDmc,
|
||||||
new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
|
new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
|
||||||
|
@ -264,21 +264,6 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
update.setLabel(label.toString(), 0);
|
update.setLabel(label.toString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
* @see org.eclipse.dd.dsf.ui.viewmodel.AbstractVMNode#handleFailedUpdate(org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void handleFailedUpdate(IViewerUpdate update) {
|
|
||||||
if (update instanceof ILabelUpdate) {
|
|
||||||
update.done();
|
|
||||||
// Avoid repainting the label if it's not available. This only slows
|
|
||||||
// down the display.
|
|
||||||
} else {
|
|
||||||
super.handleFailedUpdate(update);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#getContextsForEvent(org.eclipse.dd.dsf.ui.viewmodel.VMDelta, java.lang.Object, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
* @see org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#getContextsForEvent(org.eclipse.dd.dsf.ui.viewmodel.VMDelta, java.lang.Object, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||||
|
@ -318,6 +303,8 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
// label has changed.
|
// label has changed.
|
||||||
if (e instanceof ISuspendedDMEvent) {
|
if (e instanceof ISuspendedDMEvent) {
|
||||||
return IModelDelta.CONTENT | IModelDelta.EXPAND | IModelDelta.SELECT;
|
return IModelDelta.CONTENT | IModelDelta.EXPAND | IModelDelta.SELECT;
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
|
return IModelDelta.CONTENT | IModelDelta.EXPAND;
|
||||||
} else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) {
|
} else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) {
|
||||||
return IModelDelta.CONTENT;
|
return IModelDelta.CONTENT;
|
||||||
} else if (e instanceof ModelProxyInstalledEvent) {
|
} else if (e instanceof ModelProxyInstalledEvent) {
|
||||||
|
@ -341,13 +328,16 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
if (parent.getElement() instanceof IDMVMContext) {
|
if (parent.getElement() instanceof IDMVMContext) {
|
||||||
IExecutionDMContext threadDmc = null;
|
IExecutionDMContext threadDmc = null;
|
||||||
threadDmc = DMContexts.getAncestorOfType( ((IDMVMContext)parent.getElement()).getDMContext(), IExecutionDMContext.class);
|
threadDmc = DMContexts.getAncestorOfType( ((IDMVMContext)parent.getElement()).getDMContext(), IExecutionDMContext.class);
|
||||||
buildDeltaForSuspendedEvent((ISuspendedDMEvent)e, threadDmc, triggeringCtx, parent, nodeOffset, rm);
|
buildDeltaForSuspendedEvent(threadDmc, triggeringCtx, parent, nodeOffset, rm);
|
||||||
} else {
|
} else {
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
} else if (e instanceof FullStackRefreshEvent) {
|
||||||
|
IExecutionDMContext execDmc = ((FullStackRefreshEvent)e).getDMContext();
|
||||||
|
buildDeltaForFullStackRefreshEvent(execDmc, execDmc, parent, nodeOffset, rm);
|
||||||
} else if (e instanceof ISuspendedDMEvent) {
|
} else if (e instanceof ISuspendedDMEvent) {
|
||||||
IExecutionDMContext execDmc = ((ISuspendedDMEvent)e).getDMContext();
|
IExecutionDMContext execDmc = ((ISuspendedDMEvent)e).getDMContext();
|
||||||
buildDeltaForSuspendedEvent((ISuspendedDMEvent)e, execDmc, execDmc, parent, nodeOffset, rm);
|
buildDeltaForSuspendedEvent(execDmc, execDmc, parent, nodeOffset, rm);
|
||||||
} else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) {
|
} else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) {
|
||||||
buildDeltaForSteppingTimedOutEvent((StepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm);
|
buildDeltaForSteppingTimedOutEvent((StepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm);
|
||||||
} else if (e instanceof ModelProxyInstalledEvent) {
|
} else if (e instanceof ModelProxyInstalledEvent) {
|
||||||
|
@ -357,7 +347,55 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildDeltaForSuspendedEvent(final ISuspendedDMEvent e, final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
private void buildDeltaForSuspendedEvent(final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||||
|
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
||||||
|
IStack stackService = getServicesTracker().getService(IStack.class);
|
||||||
|
if (stackService == null || runControlService == null) {
|
||||||
|
// Required services have not initialized yet. Ignore the event.
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we are building a delta for the thread that triggered the event.
|
||||||
|
// Only then expand the stack frames and select the top one.
|
||||||
|
if (executionCtx.equals(triggeringCtx)) {
|
||||||
|
// Always expand the thread node to show the stack frames.
|
||||||
|
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
|
||||||
|
|
||||||
|
// Retrieve the list of stack frames, and mark the top frame to be selected.
|
||||||
|
getVMProvider().updateNode(
|
||||||
|
this,
|
||||||
|
new VMChildrenUpdate(
|
||||||
|
parentDelta, getVMProvider().getPresentationContext(), 0, 2,
|
||||||
|
new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleCompleted() {
|
||||||
|
final List<Object> data= getData();
|
||||||
|
if (data != null && data.size() != 0) {
|
||||||
|
parentDelta.addNode(data.get(0), 0, IModelDelta.SELECT | IModelDelta.STATE);
|
||||||
|
|
||||||
|
// Refresh the whole list of stack frames unless the target is already stepping the next command. In
|
||||||
|
// which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
|
||||||
|
// refresh the whole stack trace with every step would slow down stepping too much.
|
||||||
|
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
||||||
|
if (runControlService != null &&
|
||||||
|
triggeringCtx != null && runControlService.isStepping(triggeringCtx) &&
|
||||||
|
data.size() >= 2)
|
||||||
|
{
|
||||||
|
parentDelta.addNode( data.get(1), 1, IModelDelta.STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Even in case of errors, complete the request monitor.
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildDeltaForFullStackRefreshEvent(final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||||
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
|
||||||
IStack stackService = getServicesTracker().getService(IStack.class);
|
IStack stackService = getServicesTracker().getService(IStack.class);
|
||||||
if (stackService == null || runControlService == null) {
|
if (stackService == null || runControlService == null) {
|
||||||
|
@ -373,37 +411,8 @@ public class StackFramesVMNode extends AbstractDMVMNode
|
||||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we are building a delta for the thread that triggered the event.
|
rm.done();
|
||||||
// Only then expand the stack frames and select the top one.
|
}
|
||||||
if (executionCtx.equals(triggeringCtx)) {
|
|
||||||
// Always expand the thread node to show the stack frames.
|
|
||||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
|
|
||||||
|
|
||||||
// Retrieve the list of stack frames, and mark the top frame to be selected.
|
|
||||||
getVMProvider().updateNode(
|
|
||||||
this,
|
|
||||||
new VMChildrenUpdate(
|
|
||||||
parentDelta, getVMProvider().getPresentationContext(), -1, -1,
|
|
||||||
new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
|
|
||||||
@Override
|
|
||||||
public void handleCompleted() {
|
|
||||||
if (isSuccess() && getData().size() != 0) {
|
|
||||||
parentDelta.addNode( getData().get(0), 0, IModelDelta.SELECT | IModelDelta.STATE);
|
|
||||||
// If second frame is available repaint it, so that a "..." appears. This gives a better
|
|
||||||
// impression that the frames are not up-to date.
|
|
||||||
if (getData().size() >= 2) {
|
|
||||||
parentDelta.addNode( getData().get(1), 1, IModelDelta.STATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Even in case of errors, complete the request monitor.
|
|
||||||
rm.done();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
rm.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildDeltaForSteppingTimedOutEvent(final StepQueueManager.ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
private void buildDeltaForSteppingTimedOutEvent(final StepQueueManager.ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||||
// Repaint the stack frame images to have the running symbol.
|
// Repaint the stack frame images to have the running symbol.
|
||||||
|
|
|
@ -394,6 +394,7 @@ abstract public class AbstractVMProvider implements IVMProvider
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
clearNodes();
|
clearNodes();
|
||||||
fRootNode = null;
|
fRootNode = null;
|
||||||
|
fDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final IHasChildrenUpdate[] updates) {
|
public void update(final IHasChildrenUpdate[] updates) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
|
||||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||||
|
@ -286,14 +287,10 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
IElementUpdateTester elementTester = getActiveUpdatePolicy().getElementUpdateTester(ManualUpdatePolicy.REFRESH_EVENT);
|
IElementUpdateTester elementTester = getActiveUpdatePolicy().getElementUpdateTester(ManualUpdatePolicy.REFRESH_EVENT);
|
||||||
|
|
||||||
List<FlushMarkerKey> flushKeys = new LinkedList<FlushMarkerKey>();
|
|
||||||
|
|
||||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||||
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
flush(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
||||||
}
|
}
|
||||||
|
|
||||||
flush(flushKeys);
|
|
||||||
|
|
||||||
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
|
||||||
if (!proxyStrategy.isDisposed()) {
|
if (!proxyStrategy.isDisposed()) {
|
||||||
proxyStrategy.fireModelChanged(new ModelDelta(proxyStrategy.getRootElement(), IModelDelta.CONTENT));
|
proxyStrategy.fireModelChanged(new ModelDelta(proxyStrategy.getRootElement(), IModelDelta.CONTENT));
|
||||||
|
@ -492,97 +489,84 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
|
||||||
* parameter is null, then all entries are flushed.
|
* parameter is null, then all entries are flushed.
|
||||||
* @param archive
|
* @param archive
|
||||||
*/
|
*/
|
||||||
private void flush(List<FlushMarkerKey> flushKeys) {
|
private void flush(FlushMarkerKey flushKey) {
|
||||||
// To flush the cache data for given context, we have to iterate through all the contexts
|
// For each entry that has the given context as a parent, perform the flush.
|
||||||
// in cache. For each entry that has the given context as a parent, perform the flush.
|
|
||||||
List<FlushMarkerKey> flushKeysCopy = new ArrayList<FlushMarkerKey>(flushKeys.size());
|
|
||||||
flushKeysCopy.addAll(flushKeys);
|
|
||||||
|
|
||||||
// Iterate through the cache entries backwards. This means that we will be
|
// Iterate through the cache entries backwards. This means that we will be
|
||||||
// iterating in order of most-recently-used to least-recently-used.
|
// iterating in order of most-recently-used to least-recently-used.
|
||||||
Entry entry = fCacheListHead.fPrevious;
|
Entry entry = fCacheListHead.fPrevious;
|
||||||
while (entry != fCacheListHead && flushKeysCopy.size() != 0) {
|
while (entry != fCacheListHead) {
|
||||||
for (Iterator<FlushMarkerKey> flushKeyItr = flushKeysCopy.iterator(); flushKeyItr.hasNext();) {
|
if (entry.fKey instanceof FlushMarkerKey) {
|
||||||
FlushMarkerKey flushKey = flushKeyItr.next();
|
FlushMarkerKey entryFlushKey = (FlushMarkerKey)entry.fKey;
|
||||||
|
// If the context currently being flushed includes the flush
|
||||||
if (entry.fKey instanceof FlushMarkerKey) {
|
// context in current entry, remove the current entry since it will
|
||||||
FlushMarkerKey entryFlushKey = (FlushMarkerKey)entry.fKey;
|
// be replaced with one at the end of the list.
|
||||||
// If the context currently being flushed includes the flush
|
// Use special handling for null contexts, which we treat like it's an
|
||||||
// context in current entry, remove the current entry since it will
|
// ancestor of all other contexts.
|
||||||
// be replaced with one at the end of the list.
|
if (flushKey.includes(entryFlushKey)) {
|
||||||
// Use special handling for null contexts, which we treat like it's an
|
fCacheData.remove(entryFlushKey);
|
||||||
// ancestor of all other contexts.
|
entry.remove();
|
||||||
if (flushKey.includes(entryFlushKey)) {
|
|
||||||
fCacheData.remove(entryFlushKey);
|
|
||||||
entry.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the flush context in current entry includes the current context
|
|
||||||
// being flushed, we can stop iterating through the cache entries
|
|
||||||
// now.
|
|
||||||
if (entryFlushKey.includes(flushKey)) {
|
|
||||||
flushKeyItr.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (entry instanceof ElementDataEntry) {
|
|
||||||
ElementDataEntry elementDataEntry = (ElementDataEntry)entry;
|
// If the flush context in current entry includes the current context
|
||||||
int updateFlags = flushKey.getUpdateFlags((ElementDataKey)elementDataEntry.fKey);
|
// being flushed, we can stop iterating through the cache entries
|
||||||
if ((updateFlags & IVMUpdatePolicy.FLUSH) != 0) {
|
// now.
|
||||||
if ((updateFlags & IVMUpdatePolicy.ARCHIVE) != 0) {
|
if (entryFlushKey.includes(flushKey)) {
|
||||||
// We are saving current data for change history, check if the data is valid.
|
break;
|
||||||
// If it valid, save it for archive, if it's not valid old archive data will be used
|
}
|
||||||
// if there is any. And if there is no old archive data, just remove the cache entry.
|
}
|
||||||
for (Iterator<Map.Entry<IDMContext, Object>> itr = elementDataEntry.fDataOrStatus.entrySet().iterator();
|
else if (entry instanceof ElementDataEntry) {
|
||||||
itr.hasNext();)
|
ElementDataEntry elementDataEntry = (ElementDataEntry)entry;
|
||||||
{
|
int updateFlags = flushKey.getUpdateFlags((ElementDataKey)elementDataEntry.fKey);
|
||||||
Map.Entry<IDMContext, Object> dataOrStatusEntry = itr.next();
|
if ((updateFlags & IVMUpdatePolicy.FLUSH) != 0) {
|
||||||
if (dataOrStatusEntry.getValue() instanceof IDMData) {
|
if ((updateFlags & IVMUpdatePolicy.ARCHIVE) == IVMUpdatePolicy.ARCHIVE) {
|
||||||
elementDataEntry.fArchiveData.put(dataOrStatusEntry.getKey(), (IDMData)dataOrStatusEntry.getValue());
|
// We are saving current data for change history, check if the data is valid.
|
||||||
}
|
// If it valid, save it for archive, if it's not valid old archive data will be used
|
||||||
}
|
// if there is any. And if there is no old archive data, just remove the cache entry.
|
||||||
elementDataEntry.fDataOrStatus.clear();
|
for (Iterator<Map.Entry<IDMContext, Object>> itr = elementDataEntry.fDataOrStatus.entrySet().iterator();
|
||||||
if (elementDataEntry.fArchiveData.isEmpty()) {
|
itr.hasNext();)
|
||||||
fCacheData.remove(entry.fKey);
|
{
|
||||||
entry.remove();
|
Map.Entry<IDMContext, Object> dataOrStatusEntry = itr.next();
|
||||||
}
|
if (dataOrStatusEntry.getValue() instanceof IDMData) {
|
||||||
} else {
|
elementDataEntry.fArchiveData.put(dataOrStatusEntry.getKey(), (IDMData)dataOrStatusEntry.getValue());
|
||||||
// We are not changing the archived data. If archive data exists in the entry, leave it.
|
|
||||||
// Otherwise remove the whole entry.
|
|
||||||
if (!elementDataEntry.fArchiveData.isEmpty()) {
|
|
||||||
elementDataEntry.fDataOrStatus.clear();
|
|
||||||
} else {
|
|
||||||
fCacheData.remove(entry.fKey);
|
|
||||||
entry.remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elementDataEntry.fHasChildren = null;
|
elementDataEntry.fDataOrStatus.clear();
|
||||||
elementDataEntry.fChildrenCount = null;
|
if (elementDataEntry.fArchiveData.isEmpty()) {
|
||||||
elementDataEntry.fChildren = null;
|
fCacheData.remove(entry.fKey);
|
||||||
} else if ((updateFlags & IVMUpdatePolicy.DIRTY) != 0) {
|
entry.remove();
|
||||||
elementDataEntry.fDirty = true;
|
}
|
||||||
|
} else {
|
||||||
|
// We are not changing the archived data. If archive data exists in the entry, leave it.
|
||||||
|
// Otherwise remove the whole entry.
|
||||||
|
if (!elementDataEntry.fArchiveData.isEmpty()) {
|
||||||
|
elementDataEntry.fDataOrStatus.clear();
|
||||||
|
} else {
|
||||||
|
fCacheData.remove(entry.fKey);
|
||||||
|
entry.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
elementDataEntry.fHasChildren = null;
|
||||||
|
elementDataEntry.fChildrenCount = null;
|
||||||
|
elementDataEntry.fChildren = null;
|
||||||
|
elementDataEntry.fDirty = false;
|
||||||
|
} else if ((updateFlags & IVMUpdatePolicy.DIRTY) != 0) {
|
||||||
|
elementDataEntry.fDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entry = entry.fPrevious;
|
entry = entry.fPrevious;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FlushMarkerKey flushKey : flushKeys) {
|
// Insert a marker for this flush operation.
|
||||||
// Insert a marker for this flush operation.
|
Entry flushMarkerEntry = new Entry(flushKey);
|
||||||
Entry flushMarkerEntry = new Entry(flushKey);
|
fCacheData.put(flushKey, flushMarkerEntry);
|
||||||
fCacheData.put(flushKey, flushMarkerEntry);
|
flushMarkerEntry.insert(fCacheListHead);
|
||||||
flushMarkerEntry.insert(fCacheListHead);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleEvent(final IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
|
protected void handleEvent(final IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
|
||||||
IElementUpdateTester elementTester = getActiveUpdatePolicy().getElementUpdateTester(event);
|
IElementUpdateTester elementTester = getActiveUpdatePolicy().getElementUpdateTester(event);
|
||||||
|
|
||||||
List<FlushMarkerKey> flushKeys = new LinkedList<FlushMarkerKey>();
|
flush(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
||||||
|
|
||||||
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
|
|
||||||
|
|
||||||
flush(flushKeys);
|
|
||||||
|
|
||||||
super.handleEvent(proxyStrategy, event, rm);
|
super.handleEvent(proxyStrategy, event, rm);
|
||||||
}
|
}
|
||||||
|
@ -650,7 +634,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ElementDataKey(rootElement, node, update.getElement(), update.getElementPath());
|
return new ElementDataKey(rootElement, node, update.getViewerInput(), update.getElementPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -671,7 +655,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
|
||||||
entry.insert(fCacheListHead);
|
entry.insert(fCacheListHead);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update they root element marker:
|
// Update the root element marker:
|
||||||
// - ensure that the root marker is root markers' map,
|
// - ensure that the root marker is root markers' map,
|
||||||
// - ensure that the root marker is in the cache map,
|
// - ensure that the root marker is in the cache map,
|
||||||
// - and ensure that it's at the end of the cache.
|
// - and ensure that it's at the end of the cache.
|
||||||
|
@ -719,33 +703,38 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
|
||||||
|
|
||||||
ElementDataKey key = makeEntryKey(node, update);
|
ElementDataKey key = makeEntryKey(node, update);
|
||||||
final ElementDataEntry entry = getElementDataEntry(key);
|
final ElementDataEntry entry = getElementDataEntry(key);
|
||||||
Object dataOrStatus = entry.fDataOrStatus.get(dmc);
|
if (entry.fDirty) {
|
||||||
if(dataOrStatus != null) {
|
rm.setStatus(Status.CANCEL_STATUS);
|
||||||
if (dataOrStatus instanceof IDMData) {
|
|
||||||
rm.setData( (IDMData)dataOrStatus );
|
|
||||||
} else {
|
|
||||||
rm.setStatus((IStatus)dataOrStatus );
|
|
||||||
}
|
|
||||||
rm.done();
|
rm.done();
|
||||||
} else {
|
} else {
|
||||||
service.getExecutor().execute(new DsfRunnable() {
|
Object dataOrStatus = entry.fDataOrStatus.get(dmc);
|
||||||
public void run() {
|
if(dataOrStatus != null) {
|
||||||
service.getModelData(dmc,
|
if (dataOrStatus instanceof IDMData) {
|
||||||
new ViewerDataRequestMonitor<IDMData>(executor, update) {
|
rm.setData( dataOrStatus );
|
||||||
@Override
|
} else {
|
||||||
protected void handleCompleted() {
|
rm.setStatus((IStatus)dataOrStatus );
|
||||||
if (isSuccess()) {
|
}
|
||||||
entry.fDataOrStatus.put(dmc, getData());
|
rm.done();
|
||||||
rm.setData(getData());
|
} else {
|
||||||
} else {
|
service.getExecutor().execute(new DsfRunnable() {
|
||||||
entry.fDataOrStatus.put(dmc, getStatus());
|
public void run() {
|
||||||
rm.setStatus(getStatus());
|
service.getModelData(dmc,
|
||||||
}
|
new ViewerDataRequestMonitor<IDMData>(executor, update) {
|
||||||
rm.done();
|
@Override
|
||||||
}
|
protected void handleCompleted() {
|
||||||
});
|
if (isSuccess()) {
|
||||||
}
|
entry.fDataOrStatus.put(dmc, getData());
|
||||||
});
|
rm.setData(getData());
|
||||||
|
} else {
|
||||||
|
entry.fDataOrStatus.put(dmc, getStatus());
|
||||||
|
rm.setStatus(getStatus());
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,22 +11,34 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
|
package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||||
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.DelayedStackRefreshUpdatePolicy;
|
||||||
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.FullStackRefreshEvent;
|
||||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode;
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode;
|
||||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
|
||||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StandardProcessVMNode;
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StandardProcessVMNode;
|
||||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
|
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
import org.eclipse.dd.dsf.service.DsfSession;
|
import org.eclipse.dd.dsf.service.DsfSession;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||||
|
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxy;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||||
|
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||||
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBExitedEvent;
|
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBExitedEvent;
|
||||||
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBStartedEvent;
|
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBStartedEvent;
|
||||||
import org.eclipse.dd.mi.service.command.MIInferiorProcess.InferiorExitedDMEvent;
|
import org.eclipse.dd.mi.service.command.MIInferiorProcess.InferiorExitedDMEvent;
|
||||||
|
@ -46,7 +58,14 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
|
||||||
public class LaunchVMProvider extends AbstractDMVMProvider
|
public class LaunchVMProvider extends AbstractDMVMProvider
|
||||||
implements IDebugEventSetListener, ILaunchesListener2
|
implements IDebugEventSetListener, ILaunchesListener2
|
||||||
{
|
{
|
||||||
@ThreadSafe
|
/**
|
||||||
|
* Delay (in milliseconds) before a full stack trace will be requested.
|
||||||
|
*/
|
||||||
|
private static final int FRAME_UPDATE_DELAY= 200;
|
||||||
|
|
||||||
|
private final Map<IExecutionDMContext,ScheduledFuture<?>> fRefreshStackFramesFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
public LaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
|
public LaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
|
||||||
{
|
{
|
||||||
super(adapter, presentationContext, session);
|
super(adapter, presentationContext, session);
|
||||||
|
@ -70,6 +89,10 @@ public class LaunchVMProvider extends AbstractDMVMProvider
|
||||||
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
|
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||||
|
return new IVMUpdatePolicy[] { new DelayedStackRefreshUpdatePolicy() };
|
||||||
|
}
|
||||||
|
|
||||||
public void handleDebugEvents(final DebugEvent[] events) {
|
public void handleDebugEvents(final DebugEvent[] events) {
|
||||||
if (isDisposed()) return;
|
if (isDisposed()) return;
|
||||||
|
@ -91,6 +114,61 @@ public class LaunchVMProvider extends AbstractDMVMProvider
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleEvent(IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
|
||||||
|
super.handleEvent(proxyStrategy, event, rm);
|
||||||
|
|
||||||
|
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||||
|
final IExecutionDMContext exeContext= ((IRunControl.ISuspendedDMEvent) event).getDMContext();
|
||||||
|
ScheduledFuture<?> refreshStackFramesFuture = getRefreshFuture(exeContext);
|
||||||
|
// trigger delayed full stack frame update
|
||||||
|
if (refreshStackFramesFuture != null) {
|
||||||
|
// cancel previously scheduled frame update
|
||||||
|
refreshStackFramesFuture.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshStackFramesFuture = getSession().getExecutor().schedule(
|
||||||
|
new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
if (getSession().isActive()) {
|
||||||
|
getExecutor().execute(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// trigger full stack frame update
|
||||||
|
ScheduledFuture<?> future= fRefreshStackFramesFutures.get(exeContext);
|
||||||
|
if (future != null && !isDisposed()) {
|
||||||
|
fRefreshStackFramesFutures.remove(exeContext);
|
||||||
|
handleEvent(new FullStackRefreshEvent(exeContext));
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
FRAME_UPDATE_DELAY, TimeUnit.MILLISECONDS);
|
||||||
|
fRefreshStackFramesFutures.put(exeContext, refreshStackFramesFuture);
|
||||||
|
} else if (event instanceof IRunControl.IResumedDMEvent) {
|
||||||
|
IExecutionDMContext exeContext= ((IRunControl.IResumedDMEvent) event).getDMContext();
|
||||||
|
ScheduledFuture<?> refreshStackFramesFuture= fRefreshStackFramesFutures.get(exeContext);
|
||||||
|
if (refreshStackFramesFuture != null) {
|
||||||
|
// cancel previously scheduled frame update
|
||||||
|
refreshStackFramesFuture.cancel(false);
|
||||||
|
fRefreshStackFramesFutures.remove(exeContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the future for the given execution context or for any child of the
|
||||||
|
* given execution context.
|
||||||
|
*/
|
||||||
|
private ScheduledFuture<?> getRefreshFuture(IExecutionDMContext execCtx) {
|
||||||
|
for (IExecutionDMContext refreshCtx : fRefreshStackFramesFutures.keySet()) {
|
||||||
|
if (refreshCtx.equals(execCtx) || DMContexts.isAncestorOf(refreshCtx, execCtx)) {
|
||||||
|
return fRefreshStackFramesFutures.remove(refreshCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
DebugPlugin.getDefault().removeDebugEventListener(this);
|
DebugPlugin.getDefault().removeDebugEventListener(this);
|
||||||
|
|
Loading…
Add table
Reference in a new issue