mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-06 09:16:02 +02:00
[280461] Introduce a way to add extra executor depths to preserve the order of MI events and MI command results
This commit is contained in:
parent
29e5a63132
commit
75e6f8510f
8 changed files with 266 additions and 22 deletions
|
@ -36,6 +36,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
@ -428,12 +429,23 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
|
|
||||||
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
||||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||||
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(fCommandControl, getExecutor(), 2);
|
||||||
|
|
||||||
fContainerCommandCache = new CommandCache(getSession(), fCommandControl);
|
// These caches store the result of a command when received; also, these caches
|
||||||
|
// are manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fContainerCommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
fThreadCommandCache = new CommandCache(getSession(), fCommandControl);
|
fThreadCommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
|
|
||||||
|
// No need to use the bufferedCommandControl for the listThreadGroups cache
|
||||||
|
// because it is not being affected by events.
|
||||||
fListThreadGroupsAvailableCache = new CommandCache(getSession(), fCommandControl);
|
fListThreadGroupsAvailableCache = new CommandCache(getSession(), fCommandControl);
|
||||||
fListThreadGroupsAvailableCache.setContextAvailable(fCommandControl.getContext(), true);
|
fListThreadGroupsAvailableCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
|
|
||||||
|
@ -757,7 +769,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
|
final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
|
||||||
|
|
||||||
if (controlDmc != null) {
|
if (controlDmc != null) {
|
||||||
// Don't cache this command since the list can change at any time.
|
|
||||||
fListThreadGroupsAvailableCache.execute(
|
fListThreadGroupsAvailableCache.execute(
|
||||||
new MIListThreadGroups(controlDmc, true),
|
new MIListThreadGroups(controlDmc, true),
|
||||||
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
|
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
@ -127,7 +128,17 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
|
||||||
private void doInitialize(final RequestMonitor requestMonitor) {
|
private void doInitialize(final RequestMonitor requestMonitor) {
|
||||||
// Create the command cache
|
// Create the command cache
|
||||||
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
||||||
fCommandCache = new CommandCache(getSession(), commandControl);
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
|
||||||
|
|
||||||
|
// This cache stores the result of a command when received; also, this cache
|
||||||
|
// is manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fCommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fCommandCache.setContextAvailable(commandControl.getContext(), true);
|
fCommandCache.setContextAvailable(commandControl.getContext(), true);
|
||||||
|
|
||||||
// Register this service
|
// Register this service
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
@ -347,7 +348,17 @@ public class MIProcesses extends AbstractDsfService implements IMIProcesses, ICa
|
||||||
// new Hashtable<String, String>());
|
// new Hashtable<String, String>());
|
||||||
|
|
||||||
fCommandControl = getServicesTracker().getService(ICommandControlService.class);
|
fCommandControl = getServicesTracker().getService(ICommandControlService.class);
|
||||||
fContainerCommandCache = new CommandCache(getSession(), fCommandControl);
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(fCommandControl, getExecutor(), 2);
|
||||||
|
|
||||||
|
// This cache stores the result of a command when received; also, this cache
|
||||||
|
// is manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fContainerCommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
|
||||||
getSession().addServiceEventListener(this, null);
|
getSession().addServiceEventListener(this, null);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
@ -172,8 +173,20 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach
|
||||||
* Create the lower level register cache.
|
* Create the lower level register cache.
|
||||||
*/
|
*/
|
||||||
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
||||||
fRegisterValueCache = new CommandCache(getSession(), commandControl);
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
|
||||||
|
|
||||||
|
// This cache stores the result of a command when received; also, this cache
|
||||||
|
// is manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fRegisterValueCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fRegisterValueCache.setContextAvailable(commandControl.getContext(), true);
|
fRegisterValueCache.setContextAvailable(commandControl.getContext(), true);
|
||||||
|
|
||||||
|
// This cache is not affected by events so does not need the bufferedCommandControl
|
||||||
fRegisterNameCache = new CommandCache(getSession(), commandControl);
|
fRegisterNameCache = new CommandCache(getSession(), commandControl);
|
||||||
fRegisterNameCache.setContextAvailable(commandControl.getContext(), true);
|
fRegisterNameCache.setContextAvailable(commandControl.getContext(), true);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||||
|
@ -288,7 +289,17 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
|
|
||||||
private void doInitialize(final RequestMonitor rm) {
|
private void doInitialize(final RequestMonitor rm) {
|
||||||
fConnection = getServicesTracker().getService(ICommandControlService.class);
|
fConnection = getServicesTracker().getService(ICommandControlService.class);
|
||||||
fMICommandCache = new CommandCache(getSession(), fConnection);
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(fConnection, getExecutor(), 2);
|
||||||
|
|
||||||
|
// This cache stores the result of a command when received; also, this cache
|
||||||
|
// is manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fMICommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fMICommandCache.setContextAvailable(fConnection.getContext(), true);
|
fMICommandCache.setContextAvailable(fConnection.getContext(), true);
|
||||||
getSession().addServiceEventListener(this, null);
|
getSession().addServiceEventListener(this, null);
|
||||||
rm.done();
|
rm.done();
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
@ -190,7 +191,17 @@ public class MIStack extends AbstractDsfService
|
||||||
|
|
||||||
private void doInitialize(RequestMonitor rm) {
|
private void doInitialize(RequestMonitor rm) {
|
||||||
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
|
||||||
fMICommandCache = new CommandCache(getSession(), commandControl);
|
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
|
||||||
|
|
||||||
|
// This cache stores the result of a command when received; also, this cache
|
||||||
|
// is manipulated when receiving events. Currently, events are received after
|
||||||
|
// three scheduling of the executor, while command results after only one. This
|
||||||
|
// can cause problems because command results might be processed before an event
|
||||||
|
// that actually arrived before the command result.
|
||||||
|
// To solve this, we use a bufferedCommandControl that will delay the command
|
||||||
|
// result by two scheduling of the executor.
|
||||||
|
// See bug 280461
|
||||||
|
fMICommandCache = new CommandCache(getSession(), bufferedCommandControl);
|
||||||
fMICommandCache.setContextAvailable(commandControl.getContext(), true);
|
fMICommandCache.setContextAvailable(commandControl.getContext(), true);
|
||||||
fRunControl = getServicesTracker().getService(IRunControl.class);
|
fRunControl = getServicesTracker().getService(IRunControl.class);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 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.cdt.dsf.debug.service.command;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command control which delays the <strong>results</strong> of commands
|
||||||
|
* sent to a command control, as well as events from the command control.
|
||||||
|
* The delay is specified in the constructor using a number of executor
|
||||||
|
* dispatch cycles.
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
*/
|
||||||
|
public class BufferedCommandControl implements ICommandControl {
|
||||||
|
|
||||||
|
private DsfExecutor fExecutor;
|
||||||
|
private ICommandControl fControlDelegate;
|
||||||
|
private int fDepth;
|
||||||
|
|
||||||
|
private ICommandListener fCommandListener = new ICommandListener() {
|
||||||
|
public void commandQueued(ICommandToken token) {
|
||||||
|
for (ICommandListener processor : fCommandProcessors) {
|
||||||
|
processor.commandQueued(token);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void commandRemoved(ICommandToken token) {
|
||||||
|
for (ICommandListener processor : fCommandProcessors) {
|
||||||
|
processor.commandRemoved(token);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void commandSent(final ICommandToken token) {
|
||||||
|
for (ICommandListener processor : fCommandProcessors) {
|
||||||
|
processor.commandSent(token);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void commandDone(final ICommandToken token, final ICommandResult result) {
|
||||||
|
buffer(fDepth, new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
for (ICommandListener processor : fCommandProcessors) {
|
||||||
|
processor.commandDone(token, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
private IEventListener fEventListener = new IEventListener() {
|
||||||
|
public void eventReceived(final Object output) {
|
||||||
|
buffer(fDepth, new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
for (IEventListener processor : fEventProcessors) {
|
||||||
|
processor.eventReceived(output);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final List<ICommandListener> fCommandProcessors = new ArrayList<ICommandListener>();
|
||||||
|
private final List<IEventListener> fEventProcessors = new ArrayList<IEventListener>();
|
||||||
|
|
||||||
|
public BufferedCommandControl(ICommandControl controlDelegate, DsfExecutor executor, int depth) {
|
||||||
|
fControlDelegate = controlDelegate;
|
||||||
|
fExecutor = executor;
|
||||||
|
fDepth = depth;
|
||||||
|
assert fDepth > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCommandListener(ICommandListener listener) {
|
||||||
|
if (fCommandProcessors.isEmpty()) {
|
||||||
|
fControlDelegate.addCommandListener(fCommandListener);
|
||||||
|
}
|
||||||
|
fCommandProcessors.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void removeCommandListener(ICommandListener listener) {
|
||||||
|
fCommandProcessors.remove(listener);
|
||||||
|
if (fCommandProcessors.isEmpty()) {
|
||||||
|
fControlDelegate.removeCommandListener(fCommandListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEventListener(IEventListener listener) {
|
||||||
|
if (fEventProcessors.isEmpty()) {
|
||||||
|
fControlDelegate.addEventListener(fEventListener);
|
||||||
|
}
|
||||||
|
fEventProcessors.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeEventListener(IEventListener listener) {
|
||||||
|
fEventProcessors.remove(listener);
|
||||||
|
if (fEventProcessors.isEmpty()) {
|
||||||
|
fControlDelegate.removeEventListener(fEventListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public <V extends ICommandResult> ICommandToken queueCommand(final ICommand<V> command, final DataRequestMonitor<V> rm) {
|
||||||
|
return fControlDelegate.queueCommand(
|
||||||
|
command,
|
||||||
|
new DataRequestMonitor<V>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
buffer(fDepth, new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
rm.setData(getData());
|
||||||
|
rm.setStatus(getStatus());
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCommand(ICommandToken token) {
|
||||||
|
fControlDelegate.removeCommand(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buffer(final int depth, final DsfRunnable runnable) {
|
||||||
|
if (depth == 0) {
|
||||||
|
runnable.run();
|
||||||
|
} else {
|
||||||
|
fExecutor.execute(new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
buffer(depth - 1, runnable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,7 +22,9 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.internal.DsfPlugin;
|
import org.eclipse.cdt.dsf.internal.DsfPlugin;
|
||||||
|
@ -118,6 +120,13 @@ public class CommandCache implements ICommandListener
|
||||||
|
|
||||||
private DsfSession fSession;
|
private DsfSession fSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command control to be used to send commands to the backend.
|
||||||
|
* In certain cases, a {@link BufferedCommandControl} should be used
|
||||||
|
* to artificially delay the processing of command results; these
|
||||||
|
* artificial delays are important to keep events and command results
|
||||||
|
* ordered as received by the backend.
|
||||||
|
*/
|
||||||
private ICommandControl fCommandControl;
|
private ICommandControl fCommandControl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -384,7 +393,24 @@ public class CommandCache implements ICommandListener
|
||||||
|
|
||||||
finalCachedCmd.fToken = fCommandControl.queueCommand(
|
finalCachedCmd.fToken = fCommandControl.queueCommand(
|
||||||
finalCachedCmd.getCommand(),
|
finalCachedCmd.getCommand(),
|
||||||
new DataRequestMonitor<ICommandResult>(fSession.getExecutor(), null) {
|
new DataRequestMonitor<ICommandResult>(ImmediateExecutor.getInstance(), null) {
|
||||||
|
@Override
|
||||||
|
public synchronized void done() {
|
||||||
|
// protect against the cache being called in non-session thread, but at
|
||||||
|
// the same time avoid adding extra dispatch cycles to command processing.
|
||||||
|
if (fSession.getExecutor().isInExecutorThread()) {;
|
||||||
|
super.done();
|
||||||
|
} else {
|
||||||
|
fSession.getExecutor().execute(new DsfRunnable() {
|
||||||
|
public void run() {
|
||||||
|
superDone();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void superDone() {
|
||||||
|
super.done();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void handleCompleted() {
|
public void handleCompleted() {
|
||||||
|
|
||||||
|
@ -462,20 +488,21 @@ public class CommandCache implements ICommandListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
// Save the command result in cache, but only if the command's context
|
||||||
* This is an original request which completed. Indicate success or
|
// is still available. Otherwise an error may get cached incorrectly.
|
||||||
* failure to the original requesters.
|
if (isTargetAvailable(context)) {
|
||||||
*/
|
CommandResultInfo resultInfo = new CommandResultInfo(result, status);
|
||||||
CommandResultInfo resultInfo = new CommandResultInfo(result, status);
|
|
||||||
|
|
||||||
if (fCachedContexts.get(context) != null){
|
if (fCachedContexts.get(context) != null){
|
||||||
fCachedContexts.get(context).put(finalCachedCmd, resultInfo);
|
fCachedContexts.get(context).put(finalCachedCmd, resultInfo);
|
||||||
} else {
|
} else {
|
||||||
HashMap<CommandInfo, CommandResultInfo> map = new HashMap<CommandInfo, CommandResultInfo>();
|
HashMap<CommandInfo, CommandResultInfo> map = new HashMap<CommandInfo, CommandResultInfo>();
|
||||||
map.put(finalCachedCmd, resultInfo);
|
map.put(finalCachedCmd, resultInfo);
|
||||||
fCachedContexts.put(context, map);
|
fCachedContexts.put(context, map);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// This is an original request which completed. Indicate success or
|
||||||
|
// failure to the original requesters.
|
||||||
if (!isSuccess()) {
|
if (!isSuccess()) {
|
||||||
/*
|
/*
|
||||||
* We had some form of error with the original command. So notify the
|
* We had some form of error with the original command. So notify the
|
||||||
|
|
Loading…
Add table
Reference in a new issue