From 337235a75e44c41c46e0f94129d2c9ceea3f9984 Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Wed, 16 Jul 2008 11:02:58 +0000 Subject: [PATCH] 214386: [run control][debug view][source lookup] When stepping fast (holding down F5 key) the IP in editor does not keep up. --- .../ui/viewmodel/AbstractDebugVMAdapter.java | 65 ++ .../ui/viewmodel/SteppingController.java | 593 ++++++++++++++++++ .../launch/AbstractContainerVMNode.java | 17 + .../launch/AbstractLaunchVMProvider.java | 49 +- .../launch/AbstractThreadVMNode.java | 20 + .../DelayedStackRefreshUpdatePolicy.java | 2 + .../ui/viewmodel/launch/ExpandStackEvent.java | 2 + .../launch/FullStackRefreshEvent.java | 2 + .../launch/LaunchVMUpdateMessages.java | 3 + .../viewmodel/launch/StackFramesVMNode.java | 37 +- .../preferences/DsfDebugPreferencePage.java | 55 +- .../IntegerWithBooleanFieldEditor.java | 38 +- .../preferences/MessagesForPreferences.java | 4 + .../StringWithBooleanFieldEditor.java | 38 +- .../ui/preferences/messages.properties | 2 + .../dd/dsf/debug/ui/IDsfDebugUIConstants.java | 27 +- .../dsf/debug/ui/PreferenceInitializer.java | 4 +- .../debug/ui/actions/DsfCommandRunnable.java | 32 +- .../debug/ui/actions/DsfStepIntoCommand.java | 4 +- .../debug/ui/actions/DsfStepOverCommand.java | 4 +- .../ui/actions/DsfStepReturnCommand.java | 4 +- .../sourcelookup/DsfSourceDisplayAdapter.java | 53 +- .../InstructionPointerManager.java | 43 +- .../dsf/debug/service/IStepQueueManager.java | 42 ++ .../dsf/debug/service/StepQueueManager.java | 21 +- .../dsf/ui/viewmodel/AbstractVMAdapter.java | 294 ++++++++- .../dsf/ui/viewmodel/AbstractVMProvider.java | 36 +- .../dd/dsf/ui/viewmodel/IVMEventListener.java | 33 + .../eclipse/dd/dsf/ui/viewmodel/VMDelta.java | 2 + .../datamodel/AbstractDMVMAdapter.java | 58 ++ .../datamodel/AbstractDMVMProvider.java | 66 +- .../dd/examples/pda/ui/PDAAdapterFactory.java | 18 +- .../pda/ui/viewmodel/PDAVMAdapter.java | 9 +- .../pda/launch/PDAServicesInitSequence.java | 8 - .../launch/PDAServicesShutdownSequence.java | 7 - .../dd/gdb/internal/ui/GdbAdapterFactory.java | 17 +- .../ui/viewmodel/GdbViewModelAdapter.java | 9 +- .../launching/ServicesLaunchSequence.java | 5 - 38 files changed, 1494 insertions(+), 229 deletions(-) create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/AbstractDebugVMAdapter.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/SteppingController.java create mode 100644 plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/IStepQueueManager.java create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMEventListener.java diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/AbstractDebugVMAdapter.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/AbstractDebugVMAdapter.java new file mode 100644 index 00000000000..75a5fea790c --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/AbstractDebugVMAdapter.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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; + +import org.eclipse.dd.dsf.concurrent.DsfRunnable; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.ISteppingControlParticipant; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.ui.viewmodel.IVMProvider; +import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; + +/** + * Base class for VM adapters used for implementing a debugger integration. + * + * @since 1.1 + */ +@SuppressWarnings("restriction") +public class AbstractDebugVMAdapter extends AbstractDMVMAdapter + implements ISteppingControlParticipant +{ + + public AbstractDebugVMAdapter(DsfSession session, SteppingController controller) { + super(session); + fController = controller; + fController.addSteppingControlParticipant(this); + } + + private SteppingController fController; + + @Override + protected IVMProvider createViewModelProvider(IPresentationContext context) { + return null; + } + + @Override + public void doneHandleEvent(Object event) { + if (event instanceof IRunControl.ISuspendedDMEvent) { + final ISuspendedDMEvent suspendedEvent= (IRunControl.ISuspendedDMEvent) event; + fController.getExecutor().execute(new DsfRunnable() { + public void run() { + fController.doneStepping(suspendedEvent.getDMContext(), AbstractDebugVMAdapter.this); + }; + }); + } + } + + @Override + public void dispose() { + if (fController != null) { + fController.removeSteppingControlParticipant(this); + fController = null; + } + super.dispose(); + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/SteppingController.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/SteppingController.java new file mode 100644 index 00000000000..52874738ff5 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/SteppingController.java @@ -0,0 +1,593 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 Wind River Systems 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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.concurrent.DsfRunnable; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMEvent; +import org.eclipse.dd.dsf.datamodel.DMContexts; +import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IStepQueueManager; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent; +import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.dd.dsf.debug.service.IRunControl.StepType; +import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants; +import org.eclipse.dd.dsf.service.DsfServiceEventHandler; +import org.eclipse.dd.dsf.service.DsfServicesTracker; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; + +/** + * This class builds on top of standard run control service to provide + * functionality for step queuing and delaying. Step queuing essentially allows + * user to press and hold the step key and achieve maximum stepping speed. If + * this class is used, other service implementations, such as stack and + * expressions, can use it to avoid requesting data from debugger back end if + * another step is about to be executed. + * + * @since 1.1 + */ +public final class SteppingController implements IStepQueueManager +{ + /** + * Amount of time in milliseconds, that it takes the SteppingTimedOutEvent + * event to be issued after a step is started. + * @see SteppingTimedOutEvent + */ + public final static int STEPPING_TIMEOUT = 500; + + /** + * The depth of the step queue. In other words, the maximum number of steps + * that are queued before the step queue manager is throwing them away. + */ + public final static int STEP_QUEUE_DEPTH = 1; + + /** + * The maximum delay (in milliseconds) between steps when synchronized + * stepping is enabled. This also serves as a safeguard in the case stepping + * control participants fail to indicate completion of event processing. + */ + public final static int MAX_STEP_DELAY= 1000; + + /** + * Indicates that the given context has been stepping for some time, + * and the UI (views and actions) may need to be updated accordingly. + */ + public static final class SteppingTimedOutEvent extends AbstractDMEvent { + private SteppingTimedOutEvent(IExecutionDMContext execCtx) { + super(execCtx); + } + } + + /** + * Interface for clients interested in stepping control. When a stepping + * control participant is registered with the stepping controller, it is + * expected to call + * {@link SteppingController#doneStepping(IExecutionDMContext, ISteppingControlParticipant) + * doneStepping} as soon as a "step", i.e. a suspended event has been + * processed. If synchronized stepping is enabled, further stepping is + * blocked until all stepping control participants have indicated completion + * of event processing or the maximum timeout + * {@link SteppingController#MAX_STEP_DELAY} has been reached. + * + * @see SteppingController#addSteppingControlParticipant(ISteppingControlParticipant) + * @see SteppingController#removeSteppingControlParticipant(ISteppingControlParticipant) + */ + public interface ISteppingControlParticipant { + } + + private static class StepRequest { + StepType fStepType; + StepRequest(StepType type) { + fStepType = type; + } + } + + private final DsfSession fSession; + private final DsfServicesTracker fServicesTracker; + + private IRunControl fRunControl; + private int fQueueDepth = STEP_QUEUE_DEPTH; + + private final Map> fStepQueues = new HashMap>(); + private final Map fTimedOutFlags = new HashMap(); + private final Map> fTimedOutFutures = new HashMap>(); + + /** + * Records the time of the last step for an execution context. + */ + private final Map fLastStepTimes= new HashMap(); + + /** + * Minimum step interval in milliseconds. + */ + private int fMinStepInterval= 0; + + /** + * Whether synchronized stepping is enabled. + */ + private boolean fSynchronizedStepping; + + /** + * Map of execution contexts for which a step is in progress. + */ + private final Map> fStepInProgress = new HashMap>(); + + /** + * List of registered stepping control participants. + */ + private final List fParticipants = Collections.synchronizedList(new ArrayList()); + + /** + * Property change listener. It updates the stepping control settings. + */ + private IPropertyChangeListener fPreferencesListener; + + public SteppingController(DsfSession session) { + fSession = session; + fServicesTracker = new DsfServicesTracker(DsfDebugUIPlugin.getBundleContext(), session.getId()); + + final IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore(); + + fPreferencesListener = new IPropertyChangeListener() { + public void propertyChange(final PropertyChangeEvent event) { + handlePropertyChanged(store, event); + }}; + store.addPropertyChangeListener(fPreferencesListener); + + enableSynchronizedStepping(store.getBoolean(IDsfDebugUIConstants.PREF_SYNCHRONIZED_STEPPING_ENABLE)); + setMinimumStepInterval(store.getInt(IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL)); + } + + public void dispose() { + if (fRunControl != null) { + getSession().removeServiceEventListener(this); + } + + IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore(); + store.removePropertyChangeListener(fPreferencesListener); + + fServicesTracker.dispose(); + } + + /** + * Enables or disables synchronized stepping mode. + * In synchronized mode, after a step command is issued, + * subsequent steps are blocked for the execution context + * until {@link #doneStepping()} is called to indicate completion + * of the processing for the last step. + * + * @param enable + */ + public void enableSynchronizedStepping(boolean enable) { + fSynchronizedStepping = enable; + } + + /** + * Configure the minimum time (in milliseconds) to wait between steps. + * + * @param interval + */ + public void setMinimumStepInterval(int interval) { + fMinStepInterval = interval; + } + + /** + * Register given stepping control participant. + *

+ * Participants are obliged to call + * {@link #doneStepping(IExecutionDMContext, ISteppingControlParticipant)} + * when they have received and completed processing an + * {@link ISuspendedDMEvent}. If synchronized stepping is enabled, further + * stepping is disabled until all participants have indicated completion of + * processing the event. + *

+ * + * @param participant + */ + public void addSteppingControlParticipant(ISteppingControlParticipant participant) { + fParticipants.add(participant); + } + + /** + * Unregister given stepping control participant. + * + * @param participant + */ + public void removeSteppingControlParticipant(final ISteppingControlParticipant participant) { + fParticipants.remove(participant); + // remove participant from steps in progress + if (fSynchronizedStepping) { + getExecutor().execute(new DsfRunnable() { + public void run() { + for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) { + List participants= fStepInProgress.get(disabledCtx); + if (participants != null) { + participants.remove(participant); + if (participants.isEmpty()) { + fStepInProgress.remove(disabledCtx); + } + } + } + }}); + } + } + + /** + * Indicate that participant has completed processing of the last step. + * + * @param execCtx + */ + public void doneStepping(final IExecutionDMContext execCtx, final ISteppingControlParticipant participant) { + List participants = fStepInProgress.get(execCtx); + if (participants != null) { + participants.remove(participant); + if (participants.isEmpty()) { + doneStepping(execCtx); + } + } else { + for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) { + if (DMContexts.isAncestorOf(disabledCtx, execCtx)) { + participants = fStepInProgress.get(disabledCtx); + if (participants != null) { + participants.remove(participant); + if (participants.isEmpty()) { + doneStepping(disabledCtx); + } + } + } + } + } + } + + public DsfSession getSession() { + return fSession; + } + + /** + * All access to this class should happen through this executor. + * @return the executor this class is confined to + */ + public DsfExecutor getExecutor() { + return getSession().getExecutor(); + } + + private DsfServicesTracker getServicesTracker() { + return fServicesTracker; + } + + private IRunControl getRunControl() { + if (fRunControl == null) { + fRunControl = getServicesTracker().getService(IRunControl.class); + getSession().addServiceEventListener(this, null); + } + return fRunControl; + } + + /** + * Checks whether a step command can be queued up for given context. + */ + public void canEnqueueStep(IExecutionDMContext execCtx, StepType stepType, DataRequestMonitor rm) { + if (doCanEnqueueStep(execCtx, stepType)) { + rm.setData(true); + rm.done(); + } else { + getRunControl().canStep(execCtx, stepType, rm); + } + } + + private boolean doCanEnqueueStep(IExecutionDMContext execCtx, StepType stepType) { + return getRunControl().isStepping(execCtx) && !isSteppingTimedOut(execCtx); + } + + /** + * Check whether the next step on the given execution context should be delayed + * based on the configured step delay. + * + * @param execCtx + * @return true if the step should be delayed + */ + private boolean shouldDelayStep(IExecutionDMContext execCtx) { + return getStepDelay(execCtx) > 0; + } + + /** + * Compute the delay in milliseconds before the next step for the given context may be executed. + * + * @param execCtx + * @return the number of milliseconds before the next possible step + */ + private int getStepDelay(IExecutionDMContext execCtx) { + if (fMinStepInterval > 0) { + for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) { + if (execCtx.equals(lastStepCtx) || DMContexts.isAncestorOf(execCtx, lastStepCtx)) { + long now = System.currentTimeMillis(); + int delay= (int) (fLastStepTimes.get(lastStepCtx) + fMinStepInterval - now); + return Math.max(delay, 0); + } + } + } + return 0; + } + + private void updateLastStepTime(IExecutionDMContext execCtx) { + long now = System.currentTimeMillis(); + fLastStepTimes.put(execCtx, now); + for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) { + if (!execCtx.equals(lastStepCtx) && DMContexts.isAncestorOf(execCtx, lastStepCtx)) { + fLastStepTimes.put(lastStepCtx, now); + } + } + } + + private long getLastStepTime(IExecutionDMContext execCtx) { + if (fLastStepTimes.containsKey(execCtx)) { + return fLastStepTimes.get(execCtx); + } + for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) { + if (DMContexts.isAncestorOf(execCtx, lastStepCtx)) { + return fLastStepTimes.get(lastStepCtx); + } + } + return 0; + } + + /** + * Returns the number of step commands that are queued for given execution + * context. + */ + public int getPendingStepCount(IExecutionDMContext execCtx) { + List stepQueue = fStepQueues.get(execCtx); + if (stepQueue == null) return 0; + return stepQueue.size(); + } + + /** + * Adds a step command to the execution queue for given context. + * @param execCtx Execution context that should perform the step. + * @param stepType Type of step to execute. + */ + public void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType) { + if (shouldDelayStep(execCtx)) { + if (doCanEnqueueStep(execCtx, stepType)) { + doEnqueueStep(execCtx, stepType); + if (!getRunControl().isStepping(execCtx)) { + processStepQueue(execCtx); + } + } + } else { + getRunControl().canStep( + execCtx, stepType, new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + if (isSuccess() && getData()) { + if (isSteppingDisabled(execCtx)) { + doEnqueueStep(execCtx, stepType); + } else { + doStep(execCtx, stepType); + } + } else if (doCanEnqueueStep(execCtx, stepType)) { + doEnqueueStep(execCtx, stepType); + } + } + }); + } + } + + private void doStep(final IExecutionDMContext execCtx, final StepType stepType) { + if (fSynchronizedStepping) { + disableStepping(execCtx); + } + updateLastStepTime(execCtx); + getRunControl().step(execCtx, stepType, new RequestMonitor(getExecutor(), null)); + } + + /** + * Enqueue the given step for later execution. + * + * @param execCtx + * @param stepType + */ + private void doEnqueueStep(final IExecutionDMContext execCtx, final StepType stepType) { + List stepQueue = fStepQueues.get(execCtx); + if (stepQueue == null) { + stepQueue = new LinkedList(); + fStepQueues.put(execCtx, stepQueue); + } + if (stepQueue.size() < fQueueDepth) { + stepQueue.add(new StepRequest(stepType)); + } + } + + /** + * Returns whether the step instruction for the given context has timed out. + */ + public boolean isSteppingTimedOut(IExecutionDMContext execCtx) { + for (IExecutionDMContext timedOutCtx : fTimedOutFlags.keySet()) { + if (execCtx.equals(timedOutCtx) || DMContexts.isAncestorOf(execCtx, timedOutCtx)) { + return fTimedOutFlags.get(timedOutCtx); + } + } + return false; + } + + /** + * Process next step on queue if any. + * @param execCtx + */ + private void processStepQueue(final IExecutionDMContext execCtx) { + if (isSteppingDisabled(execCtx)) { + return; + } + if (fStepQueues.containsKey(execCtx)) { + final int stepDelay = getStepDelay(execCtx); + if (stepDelay > 0) { + getExecutor().schedule(new DsfRunnable() { + public void run() { + processStepQueue(execCtx); + } + }, stepDelay, TimeUnit.MILLISECONDS); + return; + } + List queue = fStepQueues.get(execCtx); + final StepRequest request = queue.remove(queue.size() - 1); + if (queue.isEmpty()) fStepQueues.remove(execCtx); + getRunControl().canStep( + execCtx, request.fStepType, + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + if (isSuccess() && getData()) { + doStep(execCtx, request.fStepType); + } else { + // For whatever reason we can't step anymore, so clear out + // the step queue. + fStepQueues.remove(execCtx); + } + } + }); + } + } + + /** + * Disable stepping for the given execution context. + * + * @param execCtx + */ + private void disableStepping(IExecutionDMContext execCtx) { + fStepInProgress.put(execCtx, new ArrayList(fParticipants)); + } + + /** + * Indicate that processing of the last step has completed and + * the next step can be issued. + * + * @param execCtx + */ + private void doneStepping(final IExecutionDMContext execCtx) { + if (fSynchronizedStepping) { + enableStepping(execCtx); + processStepQueue(execCtx); + } + } + + /** + * Enable stepping for the given execution context. + * + * @param execCtx + */ + private void enableStepping(final IExecutionDMContext execCtx) { + fStepInProgress.remove(execCtx); + for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) { + if (DMContexts.isAncestorOf(disabledCtx, execCtx)) { + fStepInProgress.remove(disabledCtx); + } + } + } + + private boolean isSteppingDisabled(IExecutionDMContext execCtx) { + if (fSynchronizedStepping) { + boolean disabled= fStepInProgress.containsKey(execCtx); + if (!disabled) { + for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) { + if (DMContexts.isAncestorOf(execCtx, disabledCtx)) { + disabled = true; + break; + } + } + } + if (disabled) { + long now = System.currentTimeMillis(); + long lastStepTime = getLastStepTime(execCtx); + if (now - lastStepTime > MAX_STEP_DELAY) { + enableStepping(execCtx); + disabled = false; + } + } + return disabled; + } + return false; + } + + protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) { + String property = event.getProperty(); + if (IDsfDebugUIConstants.PREF_SYNCHRONIZED_STEPPING_ENABLE.equals(property)) { + enableSynchronizedStepping(store.getBoolean(property)); + } else if (IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL.equals(property)) { + setMinimumStepInterval(store.getInt(property)); + } + } + + + /////////////////////////////////////////////////////////////////////////// + + @DsfServiceEventHandler + public void eventDispatched(final ISuspendedDMEvent e) { + // Take care of the stepping time out + fTimedOutFlags.remove(e.getDMContext()); + ScheduledFuture future = fTimedOutFutures.remove(e.getDMContext()); + if (future != null) future.cancel(false); + + // Check if there's a step pending, if so execute it + processStepQueue(e.getDMContext()); + } + + @DsfServiceEventHandler + public void eventDispatched(final IResumedDMEvent e) { + if (e.getReason().equals(StateChangeReason.STEP)) { + fTimedOutFlags.put(e.getDMContext(), Boolean.FALSE); + // We shouldn't have a stepping timeout running unless we get two + // stepping events in a row without a suspended, which would be a + // protocol error. + assert !fTimedOutFutures.containsKey(e.getDMContext()); + fTimedOutFutures.put( + e.getDMContext(), + getExecutor().schedule( + new DsfRunnable() { public void run() { + fTimedOutFutures.remove(e.getDMContext()); + + if (getSession().isActive()) { + // Issue the stepping time-out event. + getSession().dispatchEvent( + new SteppingTimedOutEvent(e.getDMContext()), + null); + } + }}, + STEPPING_TIMEOUT, TimeUnit.MILLISECONDS) + ); + + } + } + + @DsfServiceEventHandler + public void eventDispatched(SteppingTimedOutEvent e) { + fTimedOutFlags.put(e.getDMContext(), Boolean.TRUE); + enableStepping(e.getDMContext()); + } + + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractContainerVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractContainerVMNode.java index 99ec56d2a9c..38806401c26 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractContainerVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractContainerVMNode.java @@ -18,6 +18,7 @@ import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerResumedDMEvent; @@ -37,6 +38,8 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; /** * Abstract implementation of a container view model node. * Clients need to implement {@link #updateLabelInSessionThread(ILabelUpdate[])}. + * + * @since 1.1 */ @SuppressWarnings("restriction") public abstract class AbstractContainerVMNode extends AbstractDMVMNode implements IElementLabelProvider { @@ -87,6 +90,11 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement if (dmc instanceof IContainerDMContext) { return IModelDelta.CONTENT; } + } else if (e instanceof SteppingTimedOutEvent) { + if (dmc instanceof IContainerDMContext) + { + return IModelDelta.CONTENT; + } } else if (e instanceof ISteppingTimedOutEvent) { if (dmc instanceof IContainerDMContext) { @@ -129,6 +137,15 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement if (dmc instanceof IContainerDMContext) { parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT); } + } else if (e instanceof SteppingTimedOutEvent) { + // Stepping time-out indicates that a step operation is taking + // a long time, and the view needs to be refreshed to show + // the user that the program is running. + // If the step was issued for the whole container refresh + // the whole container. + if (dmc instanceof IContainerDMContext) { + parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT); + } } else if (e instanceof ISteppingTimedOutEvent) { // Stepping time-out indicates that a step operation is taking // a long time, and the view needs to be refreshed to show diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractLaunchVMProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractLaunchVMProvider.java index 01434430425..91e47fc2efc 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractLaunchVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractLaunchVMProvider.java @@ -54,7 +54,7 @@ import org.eclipse.jface.viewers.IStructuredSelection; /** - * + * @since 1.1 */ @SuppressWarnings("restriction") public class AbstractLaunchVMProvider extends AbstractDMVMProvider @@ -81,20 +81,7 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider fPreferencesListener = new IPropertyChangeListener() { public void propertyChange(final PropertyChangeEvent event) { - String property = event.getProperty(); - if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property) - || IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property)) { - if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) { - getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT)); - } else { - getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, null); - } - getExecutor().execute(new DsfRunnable() { - public void run() { - handleEvent(event); - } - }); - } + handlePropertyChanged(store, event); }}; store.addPropertyChangeListener(fPreferencesListener); } @@ -128,30 +115,33 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider } @Override - public void handleEvent(Object event) { + public void handleEvent(Object event, final RequestMonitor rm) { if (event instanceof DoubleClickEvent && !isDisposed()) { final ISelection selection= ((DoubleClickEvent) event).getSelection(); if (selection instanceof IStructuredSelection) { Object element= ((IStructuredSelection) selection).getFirstElement(); if (element instanceof IncompleteStackVMContext) { IncompleteStackVMContext incStackVmc = ((IncompleteStackVMContext) element); - IVMNode node = ((IncompleteStackVMContext) element).getVMNode(); - if (incStackVmc.getVMNode() instanceof StackFramesVMNode) { + IVMNode node = incStackVmc.getVMNode(); + if (node instanceof StackFramesVMNode && node.getVMProvider() == this) { IExecutionDMContext exeCtx= incStackVmc.getExecutionDMContext(); ((StackFramesVMNode) node).incrementStackFrameLimit(exeCtx); // replace double click event with expand stack event final ExpandStackEvent expandStackEvent = new ExpandStackEvent(exeCtx); getExecutor().execute(new DsfRunnable() { public void run() { - handleEvent(expandStackEvent); + handleEvent(expandStackEvent, null); } }); } } } + if (rm != null) { + rm.done(); + } return; } - super.handleEvent(event); + super.handleEvent(event, rm); } @Override @@ -177,7 +167,7 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider ScheduledFuture future= fRefreshStackFramesFutures.get(exeContext); if (future != null && !isDisposed()) { fRefreshStackFramesFutures.remove(exeContext); - handleEvent(new FullStackRefreshEvent(exeContext)); + handleEvent(new FullStackRefreshEvent(exeContext), null); } }}); } @@ -276,4 +266,21 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider return false; } + protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) { + String property = event.getProperty(); + if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property) + || IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property)) { + if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) { + getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT)); + } else { + getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, null); + } + getExecutor().execute(new DsfRunnable() { + public void run() { + handleEvent(event); + } + }); + } + } + } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractThreadVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractThreadVMNode.java index 2dc2ccde8eb..4e09c9472f9 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractThreadVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/AbstractThreadVMNode.java @@ -23,6 +23,7 @@ import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerResumedDMEvent; @@ -50,6 +51,8 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; /** * Abstract implementation of a thread view model node. * Clients need to implement {@link #updateLabelInSessionThread(ILabelUpdate[])}. + * + * @since 1.1 */ @SuppressWarnings("restriction") public abstract class AbstractThreadVMNode extends AbstractDMVMNode @@ -112,6 +115,15 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode rm.done(); return; } + } else if (e instanceof SteppingTimedOutEvent && + ((SteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) + { + // The timed out 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 ISteppingTimedOutEvent && ((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) { @@ -232,6 +244,8 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode return IModelDelta.NO_CHANGE; } else if (e instanceof FullStackRefreshEvent) { return IModelDelta.CONTENT; + } else if (e instanceof SteppingTimedOutEvent) { + return IModelDelta.CONTENT; } else if (e instanceof ISteppingTimedOutEvent) { return IModelDelta.CONTENT; } else if (e instanceof ModelProxyInstalledEvent) { @@ -271,6 +285,12 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode // and a fixed delay. Refresh the whole thread upon this event. parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT); rm.done(); + } else if (e instanceof SteppingTimedOutEvent) { + // Stepping time-out indicates that a step operation is taking + // a long time, and the view needs to be refreshed to show + // the user that the program is running. + parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT); + rm.done(); } else if (e instanceof ISteppingTimedOutEvent) { // Stepping time-out indicates that a step operation is taking // a long time, and the view needs to be refreshed to show diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java index 690b65ba157..31924f4a410 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java @@ -31,6 +31,8 @@ import org.eclipse.jface.viewers.TreePath; * The underlying base update policy is considered for container contexts only. * In other cases the cache data is always flushed. *

+ * + * @since 1.1 */ public class DelayedStackRefreshUpdatePolicy extends UpdatePolicyDecorator { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/ExpandStackEvent.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/ExpandStackEvent.java index dbbdb2bd336..2381ed26668 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/ExpandStackEvent.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/ExpandStackEvent.java @@ -15,6 +15,8 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; /** * Event to increase the stack frame limit for an execution context. + * + * @since 1.1 */ public class ExpandStackEvent extends AbstractDMEvent { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/FullStackRefreshEvent.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/FullStackRefreshEvent.java index 32e567e52b5..5c3a45e6b5f 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/FullStackRefreshEvent.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/FullStackRefreshEvent.java @@ -16,6 +16,8 @@ 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. + * + * @since 1.1 */ public class FullStackRefreshEvent extends AbstractDMEvent { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/LaunchVMUpdateMessages.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/LaunchVMUpdateMessages.java index f298c6f3e4f..3c71da2b583 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/LaunchVMUpdateMessages.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/LaunchVMUpdateMessages.java @@ -12,6 +12,9 @@ package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch; import org.eclipse.osgi.util.NLS; +/** + * @since 1.1 + */ public class LaunchVMUpdateMessages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchVMUpdateMessages";//$NON-NLS-1$ diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/StackFramesVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/StackFramesVMNode.java index 4f2516d8080..ffd83b5f97f 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/StackFramesVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/provisional/ui/viewmodel/launch/StackFramesVMNode.java @@ -22,10 +22,11 @@ import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants; import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IStack; import org.eclipse.dd.dsf.debug.service.IStack2; -import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; @@ -33,6 +34,7 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData; +import org.eclipse.dd.dsf.debug.service.StepQueueManager.ISteppingTimedOutEvent; import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor; @@ -65,6 +67,8 @@ public class StackFramesVMNode extends AbstractDMVMNode /** * View model context representing the end of an incomplete stack. + * + * @since 1.1 */ public class IncompleteStackVMContext extends AbstractVMContext { private final int fLevel; @@ -320,13 +324,16 @@ public class StackFramesVMNode extends AbstractDMVMNode if (idx != 0) return; final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class); + if (execDmc == null) { + return; + } IRunControl runControlService = getServicesTracker().getService(IRunControl.class); - StepQueueManager stepQueueMgrService = getServicesTracker().getService(StepQueueManager.class); - if (execDmc == null || runControlService == null || stepQueueMgrService == null) return; + SteppingController stepQueueMgr = (SteppingController) execDmc.getAdapter(SteppingController.class); + if (runControlService == null || stepQueueMgr == null) return; String imageKey = null; if (runControlService.isSuspended(execDmc) || - (runControlService.isStepping(execDmc) && !stepQueueMgrService.isSteppingTimedOut(execDmc))) + (runControlService.isStepping(execDmc) && !stepQueueMgr.isSteppingTimedOut(execDmc))) { imageKey = IDebugUIConstants.IMG_OBJS_STACKFRAME; } else { @@ -409,7 +416,9 @@ public class StackFramesVMNode extends AbstractDMVMNode 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 SteppingTimedOutEvent) { + return IModelDelta.CONTENT; + } else if (e instanceof ISteppingTimedOutEvent) { return IModelDelta.CONTENT; } else if (e instanceof ModelProxyInstalledEvent) { return IModelDelta.SELECT | IModelDelta.EXPAND; @@ -461,8 +470,10 @@ public class StackFramesVMNode extends AbstractDMVMNode clearStackFrameLimit( ((ISuspendedDMEvent)e).getDMContext() ); IExecutionDMContext execDmc = ((ISuspendedDMEvent)e).getDMContext(); buildDeltaForSuspendedEvent(execDmc, execDmc, parent, nodeOffset, rm); - } else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) { - buildDeltaForSteppingTimedOutEvent((StepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm); + } else if (e instanceof SteppingTimedOutEvent) { + buildDeltaForSteppingTimedOutEvent((SteppingTimedOutEvent)e, parent, nodeOffset, rm); + } else if (e instanceof ISteppingTimedOutEvent) { + buildDeltaForSteppingTimedOutEvent((ISteppingTimedOutEvent)e, parent, nodeOffset, rm); } else if (e instanceof ModelProxyInstalledEvent) { buildDeltaForModelProxyInstalledEvent(parent, nodeOffset, rm); } else if (e instanceof ExpandStackEvent) { @@ -549,7 +560,13 @@ public class StackFramesVMNode extends AbstractDMVMNode rm.done(); } - private void buildDeltaForSteppingTimedOutEvent(final StepQueueManager.ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { + private void buildDeltaForSteppingTimedOutEvent(final SteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { + // Repaint the stack frame images to have the running symbol. + //parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); + rm.done(); + } + + private void buildDeltaForSteppingTimedOutEvent(final ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { // Repaint the stack frame images to have the running symbol. //parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); rm.done(); @@ -662,6 +679,8 @@ public class StackFramesVMNode extends AbstractDMVMNode * Get the current active stack frame limit. If no limit is applicable {@link Integer.MAX_VALUE} is returned. * * @return the current stack frame limit + * + * @since 1.1 */ public int getStackFrameLimit(IExecutionDMContext execCtx) { if (fTemporaryLimits.containsKey(execCtx)) { @@ -691,6 +710,8 @@ public class StackFramesVMNode extends AbstractDMVMNode /** * Increment the stack frame limit by the default increment. * This implementation doubles the current limit. + * + * @since 1.1 */ public void incrementStackFrameLimit(IExecutionDMContext execCtx) { final int stackFrameLimit= getStackFrameLimit(execCtx); diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/DsfDebugPreferencePage.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/DsfDebugPreferencePage.java index 68f9fe9a314..4adfb0ca938 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/DsfDebugPreferencePage.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/DsfDebugPreferencePage.java @@ -12,6 +12,7 @@ package org.eclipse.dd.dsf.debug.internal.ui.preferences; import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants; +import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; @@ -33,7 +34,7 @@ public class DsfDebugPreferencePage extends FieldEditorPreferencePage implements * Mandatory default constructor (executable extension). */ public DsfDebugPreferencePage() { - super(GRID); + super(FLAT); IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore(); setPreferenceStore(store); setDescription(MessagesForPreferences.DsfDebugPreferencePage_description); @@ -53,26 +54,54 @@ public class DsfDebugPreferencePage extends FieldEditorPreferencePage implements @Override protected void createFieldEditors() { - Group performanceGroup= new Group(getFieldEditorParent(), SWT.NONE); + final Composite parent= getFieldEditorParent(); + final GridLayout layout= new GridLayout(); + layout.marginWidth= 0; + parent.setLayout(layout); + + Group performanceGroup= new Group(parent, SWT.NONE); performanceGroup.setText(MessagesForPreferences.DsfDebugPreferencePage_performanceGroup_label); - performanceGroup.setLayout(new GridLayout()); - GridData gd= new GridData(GridData.FILL_HORIZONTAL); - gd.verticalIndent= 5; - performanceGroup.setLayoutData(gd); - - Composite innerParent= new Composite(performanceGroup, SWT.NONE); - innerParent.setLayout(new GridLayout()); - innerParent.setLayoutData(gd); - + GridLayout groupLayout= new GridLayout(3, false); + performanceGroup.setLayout(groupLayout); + performanceGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // stack frame limit IntegerFieldEditor limitEditor= new IntegerWithBooleanFieldEditor( IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE, IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, MessagesForPreferences.DsfDebugPreferencePage_limitStackFrames_label, - innerParent); + performanceGroup); limitEditor.setValidRange(1, Integer.MAX_VALUE); - limitEditor.fillIntoGrid(innerParent, 3); + limitEditor.fillIntoGrid(performanceGroup, 3); addField(limitEditor); + + // sync stepping speed + BooleanFieldEditor syncSteppingEditor= new BooleanFieldEditor( + IDsfDebugUIConstants.PREF_SYNCHRONIZED_STEPPING_ENABLE, + MessagesForPreferences.DsfDebugPreferencePage_syncStepping_label, + performanceGroup); + + syncSteppingEditor.fillIntoGrid(performanceGroup, 3); + addField(syncSteppingEditor); + + // minimum step interval + IntegerFieldEditor minIntervalEditor= new IntegerFieldEditor( + IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL, + MessagesForPreferences.DsfDebugPreferencePage_minStepInterval_label, + performanceGroup); + + minIntervalEditor.setValidRange(0, 10000); + minIntervalEditor.fillIntoGrid(performanceGroup, 3); + addField(minIntervalEditor); + + // need to set layout again + performanceGroup.setLayout(groupLayout); +} + + @Override + protected void adjustGridLayout() { + // do nothing } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/IntegerWithBooleanFieldEditor.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/IntegerWithBooleanFieldEditor.java index b8d310acd0c..b53cdf1d1e4 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/IntegerWithBooleanFieldEditor.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/IntegerWithBooleanFieldEditor.java @@ -14,8 +14,10 @@ import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; /** * An integer field editor with an enablement check box. @@ -42,20 +44,19 @@ public class IntegerWithBooleanFieldEditor extends IntegerFieldEditor { super.doFillIntoGrid(parent, numColumns); } - @Override - public int getNumberOfControls() { - return super.getNumberOfControls() + 1; - } - - @Override - protected void adjustForNumColumns(int numColumns) { - // the checkbox uses one column - super.adjustForNumColumns(numColumns - 1); - } - private Button getCheckboxControl(Composite parent) { if (fCheckbox == null) { - fCheckbox= new Button(parent, SWT.CHECK); + Composite inner= new Composite(parent, SWT.NULL); + final GridLayout layout= new GridLayout(2, false); + layout.marginWidth = 0; + inner.setLayout(layout); + fCheckbox= new Button(inner, SWT.CHECK); + fCheckbox.setFont(parent.getFont()); + fCheckbox.setText(getLabelText()); + // create and hide label from base class + Label label = getLabelControl(inner); + label.setText(""); //$NON-NLS-1$ + label.setVisible(false); fCheckbox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -65,11 +66,22 @@ public class IntegerWithBooleanFieldEditor extends IntegerFieldEditor { } }); } else { - checkParent(fCheckbox, parent); + checkParent(fCheckbox.getParent(), parent); } return fCheckbox; } + @Override + public Label getLabelControl(Composite parent) { + final Label label= getLabelControl(); + if (label == null) { + return super.getLabelControl(parent); + } else { + checkParent(label.getParent(), parent); + } + return label; + } + protected void valueChanged(boolean oldValue, boolean newValue) { setPresentsDefaultValue(false); if (oldValue != newValue) { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/MessagesForPreferences.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/MessagesForPreferences.java index b7b791278b9..bd38bb58f43 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/MessagesForPreferences.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/MessagesForPreferences.java @@ -20,8 +20,12 @@ class MessagesForPreferences extends NLS { public static String DsfDebugPreferencePage_description; public static String DsfDebugPreferencePage_limitStackFrames_label; + + public static String DsfDebugPreferencePage_minStepInterval_label; public static String DsfDebugPreferencePage_performanceGroup_label; + public static String DsfDebugPreferencePage_syncStepping_label; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, MessagesForPreferences.class); diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/StringWithBooleanFieldEditor.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/StringWithBooleanFieldEditor.java index 09287a158ab..4f9edd0ae0f 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/StringWithBooleanFieldEditor.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/StringWithBooleanFieldEditor.java @@ -14,8 +14,10 @@ import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; /** * A string field editor with an enablement check box. @@ -47,20 +49,19 @@ public class StringWithBooleanFieldEditor extends StringFieldEditor { super.doFillIntoGrid(parent, numColumns); } - @Override - public int getNumberOfControls() { - return super.getNumberOfControls() + 1; - } - - @Override - protected void adjustForNumColumns(int numColumns) { - // the checkbox uses one column - super.adjustForNumColumns(numColumns - 1); - } - private Button getCheckboxControl(Composite parent) { if (fCheckbox == null) { - fCheckbox= new Button(parent, SWT.CHECK); + Composite inner= new Composite(parent, SWT.NULL); + final GridLayout layout= new GridLayout(2, false); + layout.marginWidth = 0; + inner.setLayout(layout); + fCheckbox= new Button(inner, SWT.CHECK); + fCheckbox.setFont(parent.getFont()); + fCheckbox.setText(getLabelText()); + // create and hide label from base class + Label label = getLabelControl(inner); + label.setText(""); //$NON-NLS-1$ + label.setVisible(false); fCheckbox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -70,11 +71,22 @@ public class StringWithBooleanFieldEditor extends StringFieldEditor { } }); } else { - checkParent(fCheckbox, parent); + checkParent(fCheckbox.getParent(), parent); } return fCheckbox; } + @Override + public Label getLabelControl(Composite parent) { + final Label label= getLabelControl(); + if (label == null) { + return super.getLabelControl(parent); + } else { + checkParent(label.getParent(), parent); + } + return label; + } + protected void valueChanged(boolean oldValue, boolean newValue) { setPresentsDefaultValue(false); if (oldValue != newValue) { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/messages.properties b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/messages.properties index f92522e6d87..225e6b1fe2d 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/messages.properties +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/internal/ui/preferences/messages.properties @@ -11,4 +11,6 @@ DsfDebugPreferencePage_description=General settings for debugging with DSF: DsfDebugPreferencePage_limitStackFrames_label=Limit number of stack frames to +DsfDebugPreferencePage_minStepInterval_label=Minimum interval between steps (in milliseconds) DsfDebugPreferencePage_performanceGroup_label=Performance +DsfDebugPreferencePage_syncStepping_label=Synchronize stepping speed with UI updates diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/IDsfDebugUIConstants.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/IDsfDebugUIConstants.java index 4b3b6ab3e2d..57df777d292 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/IDsfDebugUIConstants.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/IDsfDebugUIConstants.java @@ -12,7 +12,9 @@ package org.eclipse.dd.dsf.debug.ui; import org.eclipse.debug.ui.IDebugUIConstants; - +/** + * @noimplement This interface is not intended to be implemented by clients. + */ public interface IDsfDebugUIConstants { /** @@ -60,15 +62,33 @@ public interface IDsfDebugUIConstants { * Integer preference to control the maximum amount of stack frames to * retrieve from the backend. Default value is 10. * @see {@link #PREF_STACK_FRAME_LIMIT_ENABLE} + * + * @since 1.1 */ public static final String PREF_STACK_FRAME_LIMIT = "stackFrameLimit"; //$NON-NLS-1$ /** - * Boolean preference whether to apply the stack frame limit preference. + * Boolean preference whether to apply the stack frame limit preference. Default is true. * @see {@link #PREF_STACK_FRAME_LIMIT} + * + * @since 1.1 */ public static final String PREF_STACK_FRAME_LIMIT_ENABLE = "stackFrameLimitEnable"; //$NON-NLS-1$ + /** + * Boolean preference whether to keep stepping speed in sync with UI updates. Default is true. + * + * @since 1.1 + */ + public static final String PREF_SYNCHRONIZED_STEPPING_ENABLE = "synchronizedSteppingEnable"; //$NON-NLS-1$ + + /** + * Integer preference to enforce a minimum time interval between steps. Default is 0. + * + * @since 1.1 + */ + public static final String PREF_MIN_STEP_INTERVAL= "minStepInterval"; //$NON-NLS-1$ + /** * Help prefixes. */ @@ -85,5 +105,8 @@ public interface IDsfDebugUIConstants { public static final String DETAIL_PANE_WORD_WRAP_ACTION = PREFIX + "detail_pane_word_wrap_action_context"; //$NON-NLS-1$ public static final String DETAIL_PANE_MAX_LENGTH_ACTION = PREFIX + "detail_pane_max_length_action_context"; //$NON-NLS-1$ + /** + * @since 1.1 + */ public static final String PREFERENCE_PAGE= PREFIX + "preference_page_context"; //$NON-NLS-1$ } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/PreferenceInitializer.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/PreferenceInitializer.java index 29eb9fa7021..b5bf689b925 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/PreferenceInitializer.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/PreferenceInitializer.java @@ -58,5 +58,7 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer { */ prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, 10); prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE, true); -} + prefs.setDefault(IDsfDebugUIConstants.PREF_SYNCHRONIZED_STEPPING_ENABLE, true); + prefs.setDefault(IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL, 0); + } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java index e842d3c91e5..66bcf9dbfdf 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfCommandRunnable.java @@ -15,8 +15,10 @@ import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.DsfRunnable; import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.datamodel.DMContexts; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IStepQueueManager; import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.dd.dsf.service.DsfServicesTracker; @@ -33,10 +35,36 @@ public abstract class DsfCommandRunnable extends DsfRunnable { public IRunControl getRunControl() { return fTracker.getService(IRunControl.class); } - public StepQueueManager getStepQueueMgr() { + /** + * @deprecated Use {@link #getStepQueueManager()} instead. + */ + @Deprecated + public StepQueueManager getStepQueueMgr() { return fTracker.getService(StepQueueManager.class); } + /** + * @since 1.1 + */ + public IStepQueueManager getStepQueueManager() { + // for backwards compatibility + IStepQueueManager mgr= getStepQueueMgr(); + if (mgr != null) { + return mgr; + } + return getSteppingController(); + } + + /** + * @since 1.1 + */ + public SteppingController getSteppingController() { + if (fContext != null) { + return (SteppingController) fContext.getAdapter(SteppingController.class); + } + return null; + } + public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) { fTracker = servicesTracker; if (element instanceof IDMVMContext) { @@ -56,7 +84,7 @@ public abstract class DsfCommandRunnable extends DsfRunnable { } if (getContext() == null) { fRequest.setStatus(makeError("Selected object does not support run control.", null)); //$NON-NLS-1$ - } else if (getRunControl() == null || getStepQueueMgr() == null) { + } else if (getRunControl() == null || getStepQueueManager() == null) { fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$ } else { doExecute(); diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepIntoCommand.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepIntoCommand.java index 5f712988ff6..40e20387800 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepIntoCommand.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepIntoCommand.java @@ -49,7 +49,7 @@ public class DsfStepIntoCommand implements IStepIntoHandler { final StepType stepType= getStepType(); fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { - getStepQueueMgr().canEnqueueStep( + getStepQueueManager().canEnqueueStep( getContext(), stepType, new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { @Override @@ -71,7 +71,7 @@ public class DsfStepIntoCommand implements IStepIntoHandler { final StepType stepType= getStepType(); fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { - getStepQueueMgr().enqueueStep(getContext(), stepType); + getStepQueueManager().enqueueStep(getContext(), stepType); } }); return true; diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepOverCommand.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepOverCommand.java index 3df804ac035..99af9e2236a 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepOverCommand.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepOverCommand.java @@ -49,7 +49,7 @@ public class DsfStepOverCommand implements IStepOverHandler { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { final StepType stepType= getStepType(); @Override public void doExecute() { - getStepQueueMgr().canEnqueueStep( + getStepQueueManager().canEnqueueStep( getContext(), stepType, new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { @Override @@ -71,7 +71,7 @@ public class DsfStepOverCommand implements IStepOverHandler { final StepType stepType= getStepType(); fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { - getStepQueueMgr().enqueueStep(getContext(), stepType); + getStepQueueManager().enqueueStep(getContext(), stepType); } }); return true; diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepReturnCommand.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepReturnCommand.java index 2977e3c3195..26871d2b26d 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepReturnCommand.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/actions/DsfStepReturnCommand.java @@ -46,7 +46,7 @@ public class DsfStepReturnCommand implements IStepReturnHandler { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { - getStepQueueMgr().canEnqueueStep( + getStepQueueManager().canEnqueueStep( getContext(), StepType.STEP_RETURN, new DataRequestMonitor(ImmediateExecutor.getInstance(), null) { @Override @@ -67,7 +67,7 @@ public class DsfStepReturnCommand implements IStepReturnHandler { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { @Override public void doExecute() { - getStepQueueMgr().enqueueStep(getContext(), StepType.STEP_RETURN); + getStepQueueManager().enqueueStep(getContext(), StepType.STEP_RETURN); } }); return true; diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java index ff7dd295931..46e389fe690 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java @@ -33,10 +33,14 @@ import org.eclipse.dd.dsf.concurrent.Query; import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.ISteppingControlParticipant; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IStack; import org.eclipse.dd.dsf.debug.service.StepQueueManager; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData; @@ -86,7 +90,7 @@ import org.eclipse.ui.texteditor.ITextEditor; * dispatch thread to synchronize access to the state data of the running jobs. */ @ThreadSafe -public class DsfSourceDisplayAdapter implements ISourceDisplay +public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControlParticipant { /** * A job to perform source lookup on the given DMC. @@ -412,8 +416,16 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay private DisplayJob fPendingDisplayJob; private ClearingJob fRunningClearingJob; private List fPendingExecDmcsToClear = new LinkedList(); - + private SteppingController fController; + public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator) { + this(session, sourceLocator, null); + } + + /** + * @since 1.1 + */ + public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator, SteppingController controller) { fSession = session; fExecutor = session.getExecutor(); fServicesTracker = new DsfServicesTracker(DsfDebugUIPlugin.getBundleContext(), session.getId()); @@ -424,9 +436,18 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay fIPManager = new InstructionPointerManager(); fSession.addServiceEventListener(this, null); + + fController = controller; + if (fController != null) { + fController.addSteppingControlParticipant(this); + } } public void dispose() { + if (fController != null) { + fController.removeSteppingControlParticipant(this); + fController = null; + } fSession.removeServiceEventListener(this); fServicesTracker.dispose(); fSourceLookup.removeParticipants(new ISourceLookupParticipant[] {fSourceLookupParticipant}); @@ -470,7 +491,9 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay private void startLookupJob(final IDMContext dmc, final IWorkbenchPage page) { // If there is a previous lookup job running, cancel it. if (fRunningLookupJob != null) { - fRunningLookupJob.cancel(); + if (fRunningLookupJob.cancel()) { + doneSourceLookup(fRunningLookupJob.getDmc()); + } } fRunningLookupJob = new LookupJob(dmc, page); @@ -500,8 +523,22 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay fRunningDisplayJob = nextDisplayJob; fRunningDisplayJob.schedule(); } + doneSourceLookup(lookupResult.getDmc()); } + private void doneSourceLookup(IDMContext context) { + if (fController != null) { + // indicate completion of step + final IExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class); + if (dmc != null) { + fController.getExecutor().execute(new DsfRunnable() { + public void run() { + fController.doneStepping(dmc, DsfSourceDisplayAdapter.this); + }; + }); + } + } + } private void serviceDisplayAndClearingJobs() { if (!fPendingExecDmcsToClear.isEmpty()) { @@ -557,16 +594,18 @@ public class DsfSourceDisplayAdapter implements ISourceDisplay startAnnotationClearingJob(e.getDMContext()); } + @DsfServiceEventHandler + public void eventDispatched(SteppingTimedOutEvent e) { + startAnnotationClearingJob(e.getDMContext()); + } + @DsfServiceEventHandler public void eventDispatched(StepQueueManager.ISteppingTimedOutEvent e) { startAnnotationClearingJob(e.getDMContext()); - } + } @DsfServiceEventHandler public void eventDispatched(IRunControl.ISuspendedDMEvent e) { - if (e.getReason() == StateChangeReason.STEP) { - startAnnotationClearingJob(e.getDMContext()); - } fPrevModelContext = null; } } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/InstructionPointerManager.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/InstructionPointerManager.java index b549a570101..bd4d19edd29 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/InstructionPointerManager.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/sourcelookup/InstructionPointerManager.java @@ -21,6 +21,7 @@ import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IStack; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.text.Position; @@ -37,7 +38,17 @@ import org.eclipse.ui.texteditor.ITextEditor; @ThreadSafe class InstructionPointerManager { + /** + * Current instruction pointer annotation type. + */ + private static final String ID_CURRENT_IP= "org.eclipse.dd.debug.currentIP"; //$NON-NLS-1$ + /** + * Secondary instruction pointer annotation type. + */ + private static final String ID_SECONDARY_IP= "org.eclipse.dd.debug.secondaryIP"; //$NON-NLS-1$ + + /** * Editor annotation object for instruction pointers. */ static class IPAnnotation extends Annotation { @@ -61,7 +72,7 @@ class InstructionPointerManager { fFrame = frame; fImage = image; } - + /** * Returns this annotation's image. * @@ -170,15 +181,19 @@ class InstructionPointerManager { String text; Image image; if (isTopFrame) { - id = "org.eclipse.dd.debug.currentIP"; //$NON-NLS-1$ + id = ID_CURRENT_IP; text = "Debug Current Instruction Pointer"; //$NON-NLS-1$ image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER_TOP); } else { - id = "org.eclipse.dd.debug.secondaryIP"; //$NON-NLS-1$ + id = ID_SECONDARY_IP; text = "Debug Call Stack"; //$NON-NLS-1$ image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER); } + if (isTopFrame) { + // remove other top-frame IP annotation(s) for this execution-context + removeAnnotations(DMContexts.getAncestorOfType(frame.getParents()[0], IExecutionDMContext.class)); + } Annotation annotation = new IPAnnotation(frame, id, text, image); // Add the annotation at the position to the editor's annotation model. @@ -202,10 +217,28 @@ class InstructionPointerManager { removeAnnotation(wrapper.getTextEditor(), wrapper.getAnnotation()); wrapperItr.remove(); } - } + } } } - + + /** + * Remove all top-frame annotations associated with the specified debug target that this class + * is tracking. + */ + public void removeTopFrameAnnotations(IRunControl.IExecutionDMContext execDmc) { + // Retrieve the mapping of threads to context lists + synchronized(fAnnotationWrappers) { + for (Iterator wrapperItr = fAnnotationWrappers.iterator(); wrapperItr.hasNext();) { + AnnotationWrapper wrapper = wrapperItr.next(); + if (DMContexts.isAncestorOf(wrapper.getFrameDMC(), execDmc) + && ID_CURRENT_IP.equals(wrapper.getAnnotation().getType())) { + removeAnnotation(wrapper.getTextEditor(), wrapper.getAnnotation()); + wrapperItr.remove(); + } + } + } + } + /** Removes all annotations tracked by this manager */ public void removeAllAnnotations() { synchronized(fAnnotationWrappers) { diff --git a/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/IStepQueueManager.java b/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/IStepQueueManager.java new file mode 100644 index 00000000000..30573fd84cc --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/IStepQueueManager.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * 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.service; + +import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.StepType; +import org.eclipse.dd.dsf.service.DsfSession; + +/** + * @since 1.1 + */ +@ConfinedToDsfExecutor("getSession().getExecutor()") +public interface IStepQueueManager { + + /** + * Returns the session for which this step queue manager is used. + */ + public DsfSession getSession(); + + /** + * Checks whether a step command can be queued up for given context. + */ + public abstract void canEnqueueStep(IExecutionDMContext execCtx, StepType stepType, DataRequestMonitor rm); + + /** + * Adds a step command to the execution queue for given context. + * @param execCtx Execution context that should perform the step. + * @param stepType Type of step to execute. + */ + public abstract void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType); + +} diff --git a/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/StepQueueManager.java b/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/StepQueueManager.java index 838d865f8cc..a5389516bb7 100644 --- a/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/StepQueueManager.java +++ b/plugins/org.eclipse.dd.dsf.debug/src/org/eclipse/dd/dsf/debug/service/StepQueueManager.java @@ -41,11 +41,14 @@ import org.osgi.framework.BundleContext; * is used, other service implementations, such as stack and expressions, can * use it to avoid requesting data from debugger back end if another step is * about to be executed. + * + * @deprecated The functionality has been integrated in the UI layer. */ -public class StepQueueManager extends AbstractDsfService +@Deprecated +public class StepQueueManager extends AbstractDsfService implements IStepQueueManager { /** - * Amount of time in miliseconds, that it takes the ISteppingTimedOutEvent + * Amount of time in milliseconds, that it takes the ISteppingTimedOutEvent * event to be issued after a step is started. * @see ISteppingTimedOutEvent */ @@ -113,9 +116,9 @@ public class StepQueueManager extends AbstractDsfService return DsfDebugPlugin.getBundleContext(); } - /** - * Checks whether a step command can be queued up for given context. - */ + /* + * @see org.eclipse.dd.dsf.debug.service.IStepQueueManager#canEnqueueStep(org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext, org.eclipse.dd.dsf.debug.service.IRunControl.StepType, org.eclipse.dd.dsf.concurrent.DataRequestMonitor) + */ public void canEnqueueStep(IExecutionDMContext execCtx, StepType stepType, DataRequestMonitor rm) { if (doCanEnqueueStep(execCtx, stepType)) { rm.setData(true); @@ -139,11 +142,9 @@ public class StepQueueManager extends AbstractDsfService return stepQueue.size(); } - /** - * Adds a step command to the execution queue for given context. - * @param execCtx Execution context that should perform the step. - * @param stepType Type of step to execute. - */ + /* + * @see org.eclipse.dd.dsf.debug.service.IStepQueueManager#enqueueStep(org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext, org.eclipse.dd.dsf.debug.service.IRunControl.StepType) + */ public void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType) { fRunControl.canStep( execCtx, stepType, new DataRequestMonitor(getExecutor(), null) { diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java index 91adfafa113..0e07e4d4a20 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java @@ -10,14 +10,20 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; 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.DsfRunnable; import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.ThreadSafe; import org.eclipse.dd.dsf.internal.ui.DsfUIPlugin; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; @@ -28,6 +34,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.jface.viewers.TreePath; /** * Base implementation for View Model Adapters. The implementation uses @@ -38,10 +45,140 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; @SuppressWarnings("restriction") abstract public class AbstractVMAdapter implements IVMAdapter { - private boolean fDisposed; + + /** + * Interface for a viewer update which can be "monitored". + */ + interface IMonitoredUpdate extends IViewerUpdate { + boolean isDone(); + void setMonitor(RequestMonitor monitor); + } + + /** + * Wraps an IViewerUpdate to add a request monitor. + */ + abstract static class MonitoredUpdate implements IMonitoredUpdate { + + protected IViewerUpdate fDelegate; + private boolean fIsDone; + private RequestMonitor fMonitor; + + MonitoredUpdate(IViewerUpdate update) { + fDelegate = update; + } + + public boolean isDone() { + return fIsDone; + } + + public void setMonitor(RequestMonitor monitor) { + fMonitor = monitor; + if (fIsDone) { + monitor.done(); + } + } + + public Object getElement() { + return fDelegate.getElement(); + } + + public TreePath getElementPath() { + return fDelegate.getElementPath(); + } + + public IPresentationContext getPresentationContext() { + return fDelegate.getPresentationContext(); + } + + public Object getViewerInput() { + return fDelegate.getViewerInput(); + } + + public void cancel() { + fDelegate.cancel(); + if (!fIsDone) { + fIsDone = true; + if (fMonitor != null) { + fMonitor.done(); + } + } + } + + public void done() { + fDelegate.done(); + if (!fIsDone) { + fIsDone = true; + if (fMonitor != null) { + fMonitor.done(); + } + } + } + + public IStatus getStatus() { + return fDelegate.getStatus(); + } + + public boolean isCanceled() { + return fDelegate.isCanceled(); + } + + public void setStatus(IStatus status) { + fDelegate.setStatus(status); + } + + } + + static class MonitoredChildrenUpdate extends MonitoredUpdate implements IChildrenUpdate { + public MonitoredChildrenUpdate(IChildrenUpdate update) { + super(update); + } + + public int getLength() { + return ((IChildrenUpdate)fDelegate).getLength(); + } + + public int getOffset() { + return ((IChildrenUpdate)fDelegate).getOffset(); + } + + public void setChild(Object child, int offset) { + ((IChildrenUpdate)fDelegate).setChild(child, offset); + } + + } + + static class MonitoredHasChildrenUpdate extends MonitoredUpdate implements IHasChildrenUpdate { + public MonitoredHasChildrenUpdate(IHasChildrenUpdate update) { + super(update); + } + + public void setHasChilren(boolean hasChildren) { + ((IHasChildrenUpdate)fDelegate).setHasChilren(hasChildren); + } + + } + + static class MonitoredChildrenCountUpdate extends MonitoredUpdate implements IChildrenCountUpdate { + public MonitoredChildrenCountUpdate(IChildrenCountUpdate update) { + super(update); + } + + public void setChildCount(int numChildren) { + ((IChildrenCountUpdate)fDelegate).setChildCount(numChildren); + } + + } + + + private boolean fDisposed; private final Map fViewModelProviders = - Collections.synchronizedMap( new HashMap() ); + Collections.synchronizedMap( new HashMap() ); + + /** + * List of IViewerUpdates pending after processing an event. + */ + private final List fPendingUpdates = new ArrayList(); /** * Constructor for the View Model session. It is tempting to have the @@ -70,6 +207,16 @@ abstract public class AbstractVMAdapter implements IVMAdapter } } + /** + * Enumerate the VM providers. + * @return An instance of {@link Iterable} + * + * @since 1.1 + */ + protected Iterable getVMProviderIterable() { + return fViewModelProviders.values(); + } + public void dispose() { IVMProvider[] providers = new IVMProvider[0]; synchronized(fViewModelProviders) { @@ -91,31 +238,29 @@ abstract public class AbstractVMAdapter implements IVMAdapter } } + /** + * @return whether this VM adapter is disposed. + * + * @since 1.1 + */ + public boolean isDisposed() { + return fDisposed; + } + public void update(IHasChildrenUpdate[] updates) { - IVMProvider provider = getVMProvider(updates[0].getPresentationContext()); - if (provider != null) { - updateProvider(provider, updates); - } else { - for (IViewerUpdate update : updates) { - update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, - "No model provider for update " + update, null)); //$NON-NLS-1$ - } - } + handleUpdate(updates); } public void update(IChildrenCountUpdate[] updates) { - IVMProvider provider = getVMProvider(updates[0].getPresentationContext()); - if (provider != null) { - updateProvider(provider, updates); - } else { - for (IViewerUpdate update : updates) { - update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, - "No model provider for update " + update, null)); //$NON-NLS-1$ - } - } + handleUpdate(updates); } public void update(final IChildrenUpdate[] updates) { + handleUpdate(updates); + } + + private void handleUpdate(IViewerUpdate[] updates) { + updates = wrapUpdates(updates); IVMProvider provider = getVMProvider(updates[0].getPresentationContext()); if (provider != null) { updateProvider(provider, updates); @@ -123,10 +268,11 @@ abstract public class AbstractVMAdapter implements IVMAdapter for (IViewerUpdate update : updates) { update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "No model provider for update " + update, null)); //$NON-NLS-1$ + update.done(); } } } - + private void updateProvider(final IVMProvider provider, final IViewerUpdate[] updates) { try { provider.getExecutor().execute(new Runnable() { @@ -187,4 +333,110 @@ abstract public class AbstractVMAdapter implements IVMAdapter */ @ThreadSafe abstract protected IVMProvider createViewModelProvider(IPresentationContext context); + + /** + * Dispatch given event to VM providers interested in events. + * + * @since 1.1 + */ + protected final void handleEvent(final Object event) { + final List eventListeners = new ArrayList(); + + aboutToHandleEvent(event); + + for (IVMProvider vmProvider : getVMProviderIterable()) { + if (vmProvider instanceof IVMEventListener) { + eventListeners.add((IVMEventListener)vmProvider); + } + } + + if (!eventListeners.isEmpty()) { + synchronized (fPendingUpdates) { + fPendingUpdates.clear(); + } + // TODO which executor to use? + final Executor executor= eventListeners.get(0).getExecutor(); + final CountingRequestMonitor crm = new CountingRequestMonitor(executor, null) { + @Override + protected void handleCompleted() { + if (isDisposed()) { + return; + } + // The event listeners have completed processing the event. + // Now monitor completion of viewer updates issued while dispatching the event + final CountingRequestMonitor updatesMonitor = new CountingRequestMonitor(executor, null) { + @Override + protected void handleCompleted() { + if (isDisposed()) { + return; + } + doneHandleEvent(event); + } + }; + synchronized (fPendingUpdates) { + int pending = fPendingUpdates.size(); + updatesMonitor.setDoneCount(pending); + for (IMonitoredUpdate update : fPendingUpdates) { + update.setMonitor(updatesMonitor); + } + fPendingUpdates.clear(); + } + } + }; + crm.setDoneCount(eventListeners.size()); + + for (final IVMEventListener vmEventListener : eventListeners) { + vmEventListener.getExecutor().execute(new DsfRunnable() { + public void run() { + vmEventListener.handleEvent(event, crm); + }}); + } + } + } + + private IViewerUpdate[] wrapUpdates(IViewerUpdate[] updates) { + if (updates.length == 0) { + return updates; + } + int i = 0; + synchronized (fPendingUpdates) { + for (IViewerUpdate update : updates) { + IMonitoredUpdate wrap= createMonitoredUpdate(update); + updates[i++] = wrap; + fPendingUpdates.add(wrap); + } + } + return updates; + } + + private IMonitoredUpdate createMonitoredUpdate(IViewerUpdate update) { + if (update instanceof IChildrenCountUpdate) { + return new MonitoredChildrenCountUpdate(((IChildrenCountUpdate)update)); + } else if (update instanceof IHasChildrenUpdate) { + return new MonitoredHasChildrenUpdate(((IHasChildrenUpdate)update)); + } else if (update instanceof IChildrenUpdate) { + return new MonitoredChildrenUpdate(((IChildrenUpdate)update)); + } + return null; + } + + /** + * Given event is about to be handled. + * + * @param event + * + * @since 1.1 + */ + protected void aboutToHandleEvent(final Object event) { + } + + /** + * Given event has been processed by all VM event listeners. + * + * @param event + * + * @since 1.1 + */ + protected void doneHandleEvent(final Object event) { + } } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java index 9583d04bbb4..eac4f630394 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants; import org.eclipse.dd.dsf.concurrent.RequestMonitor; @@ -60,7 +61,7 @@ import org.eclipse.swt.widgets.Display; * @see IVMNode */ @SuppressWarnings("restriction") -abstract public class AbstractVMProvider implements IVMProvider +abstract public class AbstractVMProvider implements IVMProvider, IVMEventListener { /** Reference to the VM adapter that owns this provider */ @@ -204,8 +205,20 @@ abstract public class AbstractVMProvider implements IVMProvider * Processes the given event in the given provider, sending model * deltas if necessary. */ - public void handleEvent(final Object event) { - for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) { + public void handleEvent(final Object event) { + handleEvent(event, null); + } + + /** + * {@inheritDoc} + * @since 1.1 + */ + public void handleEvent(final Object event, RequestMonitor rm) { + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + final List activeModelProxies= new ArrayList(getActiveModelProxies()); + crm.setDoneCount(activeModelProxies.size()); + + for (final IVMModelProxy proxyStrategy : activeModelProxies) { if (proxyStrategy.isDeltaEvent(event)) { if (!fEventQueues.containsKey(proxyStrategy)) { fEventQueues.put(proxyStrategy, new ModelProxyEventQueue()); @@ -222,13 +235,16 @@ abstract public class AbstractVMProvider implements IVMProvider } } } + crm.done(); queue.fEventQueue.add(event); } else { - doHandleEvent(queue, proxyStrategy, event); + doHandleEvent(queue, proxyStrategy, event, crm); } + } else { + crm.done(); } } - + // Clean up model proxies that were removed. List activeProxies = getActiveModelProxies(); for (Iterator itr = fEventQueues.keySet().iterator(); itr.hasNext();) { @@ -237,8 +253,8 @@ abstract public class AbstractVMProvider implements IVMProvider } } } - - private void doHandleEvent(final ModelProxyEventQueue queue, final IVMModelProxy proxyStrategy, final Object event) { + + private void doHandleEvent(final ModelProxyEventQueue queue, final IVMModelProxy proxyStrategy, final Object event, final RequestMonitor rm) { queue.fProcessingEvent = true; handleEvent( proxyStrategy, event, @@ -247,8 +263,10 @@ abstract public class AbstractVMProvider implements IVMProvider protected void handleCompleted() { queue.fProcessingEvent = false; if (!queue.fEventQueue.isEmpty()) { - doHandleEvent(queue, proxyStrategy, queue.fEventQueue.remove(0)); - } + doHandleEvent(queue, proxyStrategy, queue.fEventQueue.remove(0), rm); + } else { + rm.done(); + } } }); } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMEventListener.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMEventListener.java new file mode 100644 index 00000000000..9c17198ddd5 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMEventListener.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.ui.viewmodel; + +import java.util.concurrent.Executor; + +import org.eclipse.dd.dsf.concurrent.RequestMonitor; + +/** + * A listener participating in event notifications sent out from VM adapter. + * + * @since 1.1 + */ +public interface IVMEventListener { + + /** + * Returns the executor that needs to be used to access this event listener. + */ + public Executor getExecutor(); + + /** + * Process the given event and indicate completion with request monitor. + */ + public abstract void handleEvent(final Object event, RequestMonitor rm); +} diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java index bfbc375bf1e..1ddd3eba1c9 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java @@ -200,6 +200,8 @@ public class VMDelta extends ModelDelta { * * @param element child element * @return corresponding delta node, or null + * + * @since 1.1 */ @Override public VMDelta getChildDelta(Object element) { diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMAdapter.java index cc874a0bed2..e562b8bbba5 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMAdapter.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMAdapter.java @@ -10,7 +10,11 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel.datamodel; +import java.util.concurrent.RejectedExecutionException; + import org.eclipse.dd.dsf.concurrent.ThreadSafe; +import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.service.DsfServiceEventHandler; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter; @@ -22,6 +26,13 @@ abstract public class AbstractDMVMAdapter extends AbstractVMAdapter { private final DsfSession fSession; + /** + * It is theoretically possible for a VM adapter to be disposed before it + * has a chance to register itself as event listener. This flag is used + * to avoid removing itself as listener in such situation. + */ + private boolean fRegisteredAsEventListener = false; + /** * Constructor for the View Model session. It is tempting to have the * adapter register itself here with the session as the model adapter, but @@ -33,12 +44,59 @@ abstract public class AbstractDMVMAdapter extends AbstractVMAdapter public AbstractDMVMAdapter(DsfSession session) { super(); fSession = session; + // Add ourselves as listener for DM events events. + try { + session.getExecutor().execute(new Runnable() { + public void run() { + if (DsfSession.isSessionActive(getSession().getId())) { + getSession().addServiceEventListener(AbstractDMVMAdapter.this, null); + fRegisteredAsEventListener = true; + } + } + }); + } catch (RejectedExecutionException e) { + // Session shut down, not much we can do but wait to be disposed. + } } + @Override + public void dispose() { + try { + getSession().getExecutor().execute(new Runnable() { + public void run() { + if (fRegisteredAsEventListener && getSession().isActive()) { + fSession.removeServiceEventListener(AbstractDMVMAdapter.this); + } + } + }); + } catch (RejectedExecutionException e) { + // Session shut down. + } + super.dispose(); + } + /** * Returns the DSF session that this adapter is associated with. * @return */ protected DsfSession getSession() { return fSession; } + /** + * Handle "data model changed" event by generating a delta object for each + * view and passing it to the corresponding view model provider. The view + * model provider is then responsible for filling-in and sending the delta + * to the viewer. + * + * @param event + * + * @since 1.1 + */ + @DsfServiceEventHandler + public final void eventDispatched(final IDMEvent event) { + // We're in session's executor thread (session in which the event originated). + if (isDisposed()) return; + + handleEvent(event); + } + } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMProvider.java index fea7cf1bc92..18e42e1c676 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/datamodel/AbstractDMVMProvider.java @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel.datamodel; -import java.util.concurrent.RejectedExecutionException; - import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.dd.dsf.datamodel.IDMEvent; import org.eclipse.dd.dsf.service.DsfServiceEventHandler; @@ -44,14 +42,6 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapt abstract public class AbstractDMVMProvider extends AbstractCachingVMProvider { private final DsfSession fSession; - - /** - * It is theoretically possible for a VMProvider to be disposed before it - * has a chance to register itself as event listener. This flag is used - * to avoid removing itself as listener in such situation. - */ - private boolean fRegisteredAsEventListener = false; - /** * Constructs the view model provider for given DSF session. The * constructor is thread-safe to allow VM provider to be constructed @@ -61,64 +51,16 @@ abstract public class AbstractDMVMProvider extends AbstractCachingVMProvider public AbstractDMVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) { super(adapter, presentationContext); fSession = session; - // Add ourselves as listener for DM events events. - try { - session.getExecutor().execute(new Runnable() { - public void run() { - if (DsfSession.isSessionActive(getSession().getId())) { - getSession().addServiceEventListener(AbstractDMVMProvider.this, null); - fRegisteredAsEventListener = true; - } - } - }); - } catch (RejectedExecutionException e) { - // Session shut down, not much we can do but wait to be disposed. - } } - /** Called to dispose the provider. */ - @Override - public void dispose() { - try { - getSession().getExecutor().execute(new Runnable() { - public void run() { - if (DsfSession.isSessionActive(getSession().getId()) && fRegisteredAsEventListener ) { - fSession.removeServiceEventListener(AbstractDMVMProvider.this); - } - } - }); - } catch (RejectedExecutionException e) { - // Session shut down. - } - super.dispose(); - } - public DsfSession getSession() { return fSession; } /** - * Handle "data model changed" event by generating a delta object for each - * view and passing it to the corresponding view model provider. The view - * model provider is then responsible for filling-in and sending the delta - * to the viewer. - * @param e + * @deprecated Kept for API compatibility reasons. + * Events are now received and dispatched by the VM adapter. */ - @DsfServiceEventHandler + @Deprecated + @DsfServiceEventHandler public void eventDispatched(final IDMEvent event) { - // We're in session's executor thread (session in which the event originated). - // Re-dispach to the view model provider executor thread and then call the - // model proxy strategy to handle the event. - if (isDisposed()) return; - - try { - getExecutor().execute(new Runnable() { - public void run() { - if (isDisposed()) return; - handleEvent(event); - } - }); - } catch (RejectedExecutionException e) { - // Ignore. This exception could be thrown if the provider is being - // shut down. - } } } diff --git a/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/PDAAdapterFactory.java b/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/PDAAdapterFactory.java index 3315c57a7db..e30d9ba61c2 100644 --- a/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/PDAAdapterFactory.java +++ b/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/PDAAdapterFactory.java @@ -17,6 +17,7 @@ import java.util.Map; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.concurrent.ThreadSafe; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory; import org.eclipse.dd.dsf.debug.ui.actions.DsfResumeCommand; import org.eclipse.dd.dsf.debug.ui.actions.DsfStepIntoCommand; @@ -62,7 +63,7 @@ import org.eclipse.debug.ui.sourcelookup.ISourceDisplay; public class PDAAdapterFactory implements IAdapterFactory, ILaunchesListener2 { /** - * Contains the set of adapters that are created for eacy launch instance. + * Contains the set of adapters that are created for each launch instance. */ @Immutable private static class LaunchAdapterSet { @@ -84,6 +85,8 @@ public class PDAAdapterFactory implements IAdapterFactory, ILaunchesListener2 final IDebugModelProvider fDebugModelProvider; final PDALaunch fLaunch; + final SteppingController fSteppingController; + private IModelSelectionPolicyFactory fModelSelectionPolicyFactory; LaunchAdapterSet(PDALaunch launch) { @@ -91,11 +94,15 @@ public class PDAAdapterFactory implements IAdapterFactory, ILaunchesListener2 fLaunch = launch; DsfSession session = launch.getSession(); + // register stepping controller + fSteppingController = new SteppingController(session); + session.registerModelAdapter(SteppingController.class, fSteppingController); + // Initialize VM - fViewModelAdapter = new PDAVMAdapter(session); + fViewModelAdapter = new PDAVMAdapter(session, fSteppingController); // Initialize source lookup - fSourceDisplayAdapter = new DsfSourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator()); + fSourceDisplayAdapter = new DsfSourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator(), fSteppingController); session.registerModelAdapter(ISourceDisplay.class, fSourceDisplayAdapter); // Default selection policy @@ -128,7 +135,7 @@ public class PDAAdapterFactory implements IAdapterFactory, ILaunchesListener2 // and debug model ID will be associated with all DMContexts from this // session. session.registerModelAdapter(ILaunch.class, fLaunch); - } +} void dispose() { DsfSession session = fLaunch.getSession(); @@ -138,6 +145,9 @@ public class PDAAdapterFactory implements IAdapterFactory, ILaunchesListener2 session.unregisterModelAdapter(ISourceDisplay.class); if (fSourceDisplayAdapter != null) fSourceDisplayAdapter.dispose(); + session.unregisterModelAdapter(SteppingController.class); + fSteppingController.dispose(); + session.unregisterModelAdapter(IModelSelectionPolicyFactory.class); session.unregisterModelAdapter(IStepIntoHandler.class); diff --git a/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/viewmodel/PDAVMAdapter.java b/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/viewmodel/PDAVMAdapter.java index 96b3036a9f5..ae438e09aa4 100644 --- a/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/viewmodel/PDAVMAdapter.java +++ b/plugins/org.eclipse.dd.examples.pda.ui/src/org/eclipse/dd/examples/pda/ui/viewmodel/PDAVMAdapter.java @@ -11,11 +11,12 @@ package org.eclipse.dd.examples.pda.ui.viewmodel; import org.eclipse.dd.dsf.concurrent.ThreadSafe; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.AbstractDebugVMAdapter; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.expression.ExpressionVMProvider; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.register.RegisterVMProvider; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.variable.VariableVMProvider; import org.eclipse.dd.dsf.service.DsfSession; -import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.dd.examples.pda.ui.viewmodel.launch.PDALaunchVMProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory; @@ -24,10 +25,10 @@ import org.eclipse.debug.ui.IDebugUIConstants; @ThreadSafe @SuppressWarnings("restriction") -public class PDAVMAdapter extends AbstractDMVMAdapter +public class PDAVMAdapter extends AbstractDebugVMAdapter { - public PDAVMAdapter(DsfSession session) { - super(session); + public PDAVMAdapter(DsfSession session, SteppingController controller) { + super(session, controller); getSession().registerModelAdapter(IColumnPresentationFactory.class, this); } diff --git a/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesInitSequence.java b/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesInitSequence.java index 1de0b2aa12f..bbdd44ed625 100644 --- a/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesInitSequence.java +++ b/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesInitSequence.java @@ -13,7 +13,6 @@ package org.eclipse.dd.examples.pda.launch; import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.Sequence; import org.eclipse.dd.dsf.debug.service.BreakpointsMediator; -import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.examples.pda.service.PDABreakpointAttributeTranslator; import org.eclipse.dd.examples.pda.service.PDABreakpoints; @@ -54,13 +53,6 @@ public class PDAServicesInitSequence extends Sequence { fRunControl.initialize(requestMonitor); } }, - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - // Start the service to manage step actions. - new StepQueueManager(fSession).initialize(requestMonitor); - } - }, new Step() { @Override public void execute(final RequestMonitor requestMonitor) { diff --git a/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesShutdownSequence.java b/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesShutdownSequence.java index 43a674abe1c..a5de87e7ac2 100644 --- a/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesShutdownSequence.java +++ b/plugins/org.eclipse.dd.examples.pda/src/org/eclipse/dd/examples/pda/launch/PDAServicesShutdownSequence.java @@ -17,7 +17,6 @@ import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants; import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.Sequence; import org.eclipse.dd.dsf.debug.service.BreakpointsMediator; -import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.service.DsfServicesTracker; import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.examples.pda.PDAPlugin; @@ -86,12 +85,6 @@ public class PDAServicesShutdownSequence extends Sequence { shutdownService(PDABreakpoints.class, requestMonitor); } }, - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - shutdownService(StepQueueManager.class, requestMonitor); - } - }, new Step() { @Override public void execute(RequestMonitor requestMonitor) { diff --git a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java index 2ea44db1a2d..4114088decd 100644 --- a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java +++ b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/GdbAdapterFactory.java @@ -19,6 +19,7 @@ import org.eclipse.cdt.debug.core.model.ISteppingModeTarget; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.concurrent.ThreadSafe; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory; import org.eclipse.dd.dsf.debug.ui.actions.DsfResumeCommand; import org.eclipse.dd.dsf.debug.ui.actions.DsfStepIntoCommand; @@ -79,15 +80,20 @@ public class GdbAdapterFactory final DsfSuspendTrigger fSuspendTrigger; final DsfSteppingModeTarget fSteppingModeTarget; final IModelSelectionPolicyFactory fModelSelectionPolicyFactory; + final SteppingController fSteppingController; SessionAdapterSet(GdbLaunch launch) { fLaunch = launch; DsfSession session = launch.getSession(); - fViewModelAdapter = new GdbViewModelAdapter(session); + // register stepping controller + fSteppingController = new SteppingController(session); + session.registerModelAdapter(SteppingController.class, fSteppingController); + + fViewModelAdapter = new GdbViewModelAdapter(session, fSteppingController); if (launch.getSourceLocator() instanceof ISourceLookupDirector) { - fSourceDisplayAdapter = new DsfSourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator()); + fSourceDisplayAdapter = new DsfSourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator(), fSteppingController); } else { fSourceDisplayAdapter = null; } @@ -137,7 +143,10 @@ public class GdbAdapterFactory session.unregisterModelAdapter(ISourceDisplay.class); if (fSourceDisplayAdapter != null) fSourceDisplayAdapter.dispose(); - + + session.unregisterModelAdapter(SteppingController.class); + fSteppingController.dispose(); + session.unregisterModelAdapter(ISteppingModeTarget.class); session.unregisterModelAdapter(IStepIntoHandler.class); session.unregisterModelAdapter(IStepOverHandler.class); @@ -147,7 +156,7 @@ public class GdbAdapterFactory session.unregisterModelAdapter(IRestart.class); session.unregisterModelAdapter(ITerminateHandler.class); session.unregisterModelAdapter(IModelSelectionPolicyFactory.class); - + fStepIntoCommand.dispose(); fStepOverCommand.dispose(); fStepReturnCommand.dispose(); diff --git a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java index 97d9f828f49..8baa60e6177 100644 --- a/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java +++ b/plugins/org.eclipse.dd.gdb.ui/src/org/eclipse/dd/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java @@ -11,12 +11,13 @@ package org.eclipse.dd.gdb.internal.ui.viewmodel; import org.eclipse.dd.dsf.concurrent.ThreadSafe; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.AbstractDebugVMAdapter; +import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.SteppingController; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.expression.ExpressionVMProvider; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.modules.ModulesVMProvider; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.register.RegisterVMProvider; import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.variable.VariableVMProvider; import org.eclipse.dd.dsf.service.DsfSession; -import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.dd.gdb.internal.ui.viewmodel.launch.LaunchVMProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory; @@ -28,10 +29,10 @@ import org.eclipse.debug.ui.IDebugUIConstants; */ @ThreadSafe @SuppressWarnings("restriction") -public class GdbViewModelAdapter extends AbstractDMVMAdapter +public class GdbViewModelAdapter extends AbstractDebugVMAdapter { - public GdbViewModelAdapter(DsfSession session) { - super(session); + public GdbViewModelAdapter(DsfSession session, SteppingController controller) { + super(session, controller); getSession().registerModelAdapter(IColumnPresentationFactory.class, this); } diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/ServicesLaunchSequence.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/ServicesLaunchSequence.java index b6d5a4dfc24..622b1ebf04c 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/ServicesLaunchSequence.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/ServicesLaunchSequence.java @@ -24,7 +24,6 @@ import org.eclipse.dd.dsf.debug.service.IRegisters; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.ISourceLookup; import org.eclipse.dd.dsf.debug.service.IStack; -import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType; @@ -55,10 +54,6 @@ public class ServicesLaunchSequence extends Sequence { fLaunch.getServiceFactory().createService(fSession, IProcesses.class).initialize(requestMonitor); }}, new Step() { @Override - public void execute(RequestMonitor requestMonitor) { - new StepQueueManager(fSession).initialize(requestMonitor); - }}, - new Step() { @Override public void execute(RequestMonitor requestMonitor) { fLaunch.getServiceFactory().createService(fSession, IMemory.class).initialize(requestMonitor); }},