1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-01 22:25:25 +02:00

[208476] Added queuing of events to the View Model cache.

This commit is contained in:
Pawel Piech 2008-04-25 16:59:57 +00:00
parent 0eb5614e96
commit 383e01aec2
7 changed files with 161 additions and 53 deletions

View file

@ -22,6 +22,7 @@ import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.register.SyncR
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.update.BreakpointHitUpdatePolicy;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.variable.SyncVariableDataAccess;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.variable.VariableVMNode;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.DefaultVMContentProviderStrategy;
@ -326,4 +327,12 @@ public class ExpressionVMProvider extends AbstractDMVMProvider
}
handleEvent(new ExpressionsChangedEvent(type, rootElements));
}
@Override
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
// To optimize the performance of the view when stepping rapidly, skip all
// other events when a suspended event is received, including older suspended
// events.
return newEvent instanceof ISuspendedDMEvent;
}
}

View file

@ -12,6 +12,7 @@ package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.register;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.numberformat.FormattedValuePreferenceStore;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.update.BreakpointHitUpdatePolicy;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
@ -99,4 +100,13 @@ public class RegisterVMProvider extends AbstractDMVMProvider
public void propertyChange(PropertyChangeEvent event) {
handleEvent(event);
}
@Override
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
// To optimize the performance of the view when stepping rapidly, skip all
// other events when a suspended event is received, including older suspended
// events.
return newEvent instanceof ISuspendedDMEvent;
}
}

View file

@ -10,6 +10,7 @@ package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.variable;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.numberformat.FormattedValuePreferenceStore;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.update.BreakpointHitUpdatePolicy;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
@ -82,4 +83,12 @@ public class VariableVMProvider extends AbstractDMVMProvider
return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
}
@Override
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
// To optimize the performance of the view when stepping rapidly, skip all
// other events when a suspended event is received, including older suspended
// events.
return newEvent instanceof ISuspendedDMEvent;
}
}

View file

@ -15,12 +15,14 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.ui.concurrent.DisplayDsfExecutor;
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
@ -123,6 +125,13 @@ abstract public class AbstractVMProvider implements IVMProvider
*/
private IRootVMNode fRootNode;
private class ModelProxyEventQueue {
private boolean fProcessingEvent = false;
private List<Object> fEventQueue = new LinkedList<Object>();
}
private Map<IVMModelProxy, ModelProxyEventQueue> fEventQueues = new HashMap<IVMModelProxy, ModelProxyEventQueue>();
/**
* Constructs the view model provider for given DSF session. The
* constructor is thread-safe to allow VM provider to be constructed
@ -198,24 +207,109 @@ abstract public class AbstractVMProvider implements IVMProvider
public void handleEvent(final Object event) {
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
if (proxyStrategy.isDeltaEvent(event)) {
proxyStrategy.createDelta(
event,
new DataRequestMonitor<IModelDelta>(getExecutor(), null) {
@Override
public void handleCompleted() {
if (isSuccess()) {
proxyStrategy.fireModelChanged(getData());
if (!fEventQueues.containsKey(proxyStrategy)) {
fEventQueues.put(proxyStrategy, new ModelProxyEventQueue());
}
final ModelProxyEventQueue queue = fEventQueues.get(proxyStrategy);
if (queue.fProcessingEvent) {
if (!queue.fEventQueue.isEmpty()) {
for (ListIterator<Object> itr = queue.fEventQueue.listIterator(queue.fEventQueue.size() - 1); itr.hasPrevious();) {
Object eventToSkip = itr.previous();
if (canSkipHandlingEvent(event, eventToSkip)) {
itr.remove();
} else {
break;
}
}
@Override public String toString() {
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
});
}
queue.fEventQueue.add(event);
} else {
doHandleEvent(queue, proxyStrategy, event);
}
}
}
// Clean up model proxies that were removed.
List<IVMModelProxy> activeProxies = getActiveModelProxies();
for (Iterator<IVMModelProxy> itr = fEventQueues.keySet().iterator(); itr.hasNext();) {
if (!activeProxies.contains(itr.next())) {
itr.remove();
}
}
}
private void doHandleEvent(final ModelProxyEventQueue queue, final IVMModelProxy proxyStrategy, final Object event) {
queue.fProcessingEvent = true;
handleEvent(
proxyStrategy, event,
new RequestMonitor(getExecutor(), null) {
@Override
protected void handleCompleted() {
queue.fProcessingEvent = false;
if (!queue.fEventQueue.isEmpty()) {
doHandleEvent(queue, proxyStrategy, queue.fEventQueue.remove(0));
}
}
});
}
/**
* Handles the given event for the given proxy strategy.
* <p>
* This method is called by the base {@link #handleEvent(Object)}
* implementation to handle the given event using the given model proxy.
* The default implementation of this method checks whether the given
* proxy is active and if the proxy is active, it is called to generate the
* delta which is then sent to the viewer.
* </p>
* @param proxyStrategy Model proxy strategy to use to process this event.
* @param event Event to process.
* @param rm Request monitor to call when processing the event is
* completed.
*/
protected void handleEvent(final IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
if (!proxyStrategy.isDisposed()) {
proxyStrategy.createDelta(
event,
new DataRequestMonitor<IModelDelta>(getExecutor(), rm) {
@Override
public void handleCompleted() {
if (isSuccess()) {
proxyStrategy.fireModelChanged(getData());
}
super.handleCompleted();
}
@Override public String toString() {
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
});
} else {
rm.done();
}
}
/**
* Determines whether processing of a given event can be skipped. This
* method is called when there are multiple events waiting to be processed
* by the provider. As new events are received from the model, they are
* compared with the events in the queue using this method, events at the
* end of the queue are tested for removal. If this method returns that a
* given event can be skipped in favor of the new event, the skipped event
* is removed from the queue. This process is repeated with the new event
* until an event which cannot be stopped is found or the queue goes empty.
* <p>
* This method may be overriden by specific view model provider
* implementations extending this abstract class.
* </p>
* @param newEvent New event that was received from the model.
* @param eventToSkip Event which is currently at the end of the queue.
* @return True if the event at the end of the queue can be skipped in
* favor of the new event.
*/
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
return false;
}
public IRootVMNode getRootVMNode() {
return fRootNode;
}

View file

@ -336,8 +336,6 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
new DataRequestMonitor<List<Object>>(getVMProvider().getExecutor(), null) {
@Override
protected void handleCompleted() {
if (isDisposed()) return;
// Check for an empty list of elements. If it's empty then we
// don't have to call the children nodes, so return here.
// No need to propagate error, there's no means or need to display it.
@ -449,13 +447,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
}
final MultiRequestMonitor<RequestMonitor> elementsDeltasMultiRequestMon =
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), null) {
@Override
protected void handleCompleted() {
if (isDisposed()) return;
requestMonitor.done();
}
};
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), requestMonitor);
// For each element from this node, create a new delta,
// and then call all the child nodes to build their delta.
@ -508,8 +500,6 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
new DataRequestMonitor<Map<IVMNode, Integer>>(getVMProvider().getExecutor(), null) {
@Override
protected void handleCompleted() {
if (isDisposed()) return;
final CountingRequestMonitor multiRm = new CountingRequestMonitor(getVMProvider().getExecutor(), requestMonitor);
int multiRmCount = 0;
@ -562,11 +552,6 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
final Integer[] counts = new Integer[childNodes.length];
final MultiRequestMonitor<RequestMonitor> childrenCountMultiRequestMon =
new MultiRequestMonitor<RequestMonitor>(getVMProvider().getExecutor(), rm) {
@Override
protected void handleCompleted() {
if (isDisposed()) return;
super.handleCompleted();
}
@Override
protected void handleSuccess() {
Map<IVMNode, Integer> data = new HashMap<IVMNode, Integer>();

View file

@ -21,6 +21,7 @@ import java.util.concurrent.Executor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMData;
import org.eclipse.dd.dsf.datamodel.IDMService;
@ -555,39 +556,16 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa
}
@Override
public void handleEvent(final Object event) {
protected void handleEvent(final IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
IElementUpdateTester elementTester = getActiveUpdatePolicy().getTesterTester(event);
List<FlushMarkerKey> flushKeys = new LinkedList<FlushMarkerKey>();
List<IVMModelProxy> proxies = new LinkedList<IVMModelProxy>();
for (final IVMModelProxy proxyStrategy : getActiveModelProxies()) {
if (proxyStrategy.isDeltaEvent(event)) {
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
proxies.add(proxyStrategy);
}
}
flushKeys.add(new FlushMarkerKey(proxyStrategy.getRootElement(), elementTester));
flush(flushKeys);
for (final IVMModelProxy proxyStrategy : proxies) {
if (!proxyStrategy.isDisposed() && proxyStrategy.isDeltaEvent(event)) {
proxyStrategy.createDelta(
event,
new DataRequestMonitor<IModelDelta>(getExecutor(), null) {
@Override
public void handleCompleted() {
if (isSuccess()) {
proxyStrategy.fireModelChanged(getData());
}
}
@Override public String toString() {
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
});
}
}
super.handleEvent(proxyStrategy, event, rm);
}
/**

View file

@ -14,10 +14,14 @@ package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
import java.util.concurrent.RejectedExecutionException;
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.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StandardProcessVMNode;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
@ -126,4 +130,23 @@ public class LaunchVMProvider extends AbstractDMVMProvider
// shut down.
}
}
@Override
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
// To optimize view performance when stepping rapidly, skip events that came
// before the last suspended events. However, the debug view can get suspended
// events for different threads, so make sure to skip only the events if they
// were in the same hierarchy as the last suspended event.
if (newEvent instanceof ISuspendedDMEvent && eventToSkip instanceof IDMEvent<?>) {
IDMContext newEventDmc = ((IDMEvent<?>)newEvent).getDMContext();
IDMContext eventToSkipDmc = ((IDMEvent<?>)eventToSkip).getDMContext();
if (newEventDmc.equals(eventToSkipDmc) || DMContexts.isAncestorOf(eventToSkipDmc, newEventDmc)) {
return true;
}
}
return false;
}
}