1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 330974: If the user selects multiple nodes in the debug view most debug commands are disabled

Change-Id: I51d15347fd28ee550e9bd2b75c61e904e75b4c8b
Reviewed-on: https://git.eclipse.org/r/5650
Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com>
IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com>
Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
Marc Khouzam 2012-04-24 22:58:22 -04:00
parent c7be116351
commit efe3dd4be6
24 changed files with 4844 additions and 68 deletions

View file

@ -9,14 +9,18 @@
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Ericsson AB - Modified for handling of multiple threads * Ericsson AB - Modified for handling of multiple threads
* Indel AG - [369622] fixed moveToLine using MinGW * Indel AG - [369622] fixed moveToLine using MinGW
* Marc Khouzam (Ericsson) - Support for operations on multiple execution contexts (bug 330974)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service; package org.eclipse.cdt.dsf.gdb.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -42,6 +46,7 @@ import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent; import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent;
import org.eclipse.cdt.dsf.debug.service.ICachingService; import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IMultiRunControl;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl;
@ -104,7 +109,7 @@ import org.osgi.framework.BundleContext;
* sync with the service state. * sync with the service state.
* @since 1.1 * @since 1.1
*/ */
public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, IMultiRunControl, ICachingService
{ {
@Immutable @Immutable
private static class ExecutionData implements IExecutionDMData2 { private static class ExecutionData implements IExecutionDMData2 {
@ -396,7 +401,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
private void doInitialize(final RequestMonitor rm) { private void doInitialize(final RequestMonitor rm) {
register(new String[]{ IRunControl.class.getName(), register(new String[]{ IRunControl.class.getName(),
IRunControl2.class.getName(), IRunControl2.class.getName(),
IMIRunControl.class.getName()}, IMIRunControl.class.getName(),
IMultiRunControl.class.getName() },
new Hashtable<String,String>()); new Hashtable<String,String>());
fConnection = getServicesTracker().getService(ICommandControlService.class); fConnection = getServicesTracker().getService(ICommandControlService.class);
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
@ -1878,4 +1884,293 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
} }
return result; return result;
} }
///////////////////////////////////////////////////////////////////////////
// IMultiRunControl implementation
///////////////////////////////////////////////////////////////////////////
// Although multi-process in only supported for GDB >= 7.2, it is simpler
// to code for the multi-process case all the time, since it is a superset
// of the single-process case.
///////////////////////////////////////////////////////////////////////////
// Multi-resume implementation:
//
// If one or more more threads of one or many processes are selected, we want to
// resume each thread (once).
//
// If one or more more processes are selected, we want to resume each process (once).
//
// If a process is selected along with one or more threads of that same process,
// what does the user want us to do? Selecting the process will resume all its
// threads, but what do we do with the selected threads? Why are they
// selected? In an attempt to be user friendly, lets assume that the user
// wants to resume the entire process, so we ignore the selected threads part of that
// process since they will be resumed anyway.
//
// The same logic applies to multi-suspend.
///////////////////////////////////////////////////////////////////////////
/** @since 4.1 */
@Override
public void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
if (fRunControlOperationsEnabled == false) {
rm.done(false);
return;
}
List<IExecutionDMContext> execDmcToResumeList = extractContextsForOperation(contexts);
// If any of the threads or processes can be resumed, we allow
// the user to perform the operation.
for (IExecutionDMContext execDmc : execDmcToResumeList) {
if (doCanResume(execDmc)) {
rm.done(true);
return;
}
}
// Didn't find anything that could be resumed.
rm.done(false);
}
/** @since 4.1 */
@Override
public void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
if (fRunControlOperationsEnabled == false) {
rm.done(false);
return;
}
List<IExecutionDMContext> execDmcToResumeList = extractContextsForOperation(contexts);
// If any of the threads or processes cannot be resumed, we don't allow
// the user to perform the operation.
for (IExecutionDMContext execDmc : execDmcToResumeList) {
if (!doCanResume(execDmc)) {
rm.done(false);
return;
}
}
// Everything can be resumed
rm.done(true);
}
/**
* {@inheritDoc}
*
* For GDB, a separate resume command will be sent, one for each context
* that can be resumed.
* @since 4.1
*/
@Override
public void resume(IExecutionDMContext[] contexts, RequestMonitor rm) {
assert contexts != null;
List<IExecutionDMContext> execDmcToResumeList = extractContextsForOperation(contexts);
CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm);
int count = 0;
// Perform resume operation on each thread or process that can be resumed
for (IExecutionDMContext execDmc : execDmcToResumeList) {
if (doCanResume(execDmc)) {
count++;
resume(execDmc, crm);
}
}
crm.setDoneCount(count);
}
///////////////////////////////////////////////////////////////////////////
// Multi-suspend implementation:
// see details of the multi-resume implementation above.
///////////////////////////////////////////////////////////////////////////
/** @since 4.1 */
@Override
public void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
if (fRunControlOperationsEnabled == false) {
rm.done(false);
return;
}
List<IExecutionDMContext> execDmcToSuspendList = extractContextsForOperation(contexts);
// If any of the threads or processes can be suspended, we allow
// the user to perform the operation.
for (IExecutionDMContext execDmc : execDmcToSuspendList) {
if (doCanSuspend(execDmc)) {
rm.done(true);
return;
}
}
// Didn't find anything that could be suspended.
rm.done(false);
}
/** @since 4.1 */
@Override
public void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
if (fRunControlOperationsEnabled == false) {
rm.done(false);
return;
}
List<IExecutionDMContext> execDmcToSuspendList = extractContextsForOperation(contexts);
// If any of the threads or processes cannot be suspended, we don't allow
// the user to perform the operation.
for (IExecutionDMContext execDmc : execDmcToSuspendList) {
if (!doCanSuspend(execDmc)) {
rm.done(false);
return;
}
}
// Everything can be suspended
rm.done(true);
}
/** @since 4.1 */
@Override
public void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
List<IExecutionDMContext> execDmcSuspendedList = extractContextsForOperation(contexts);
// Look for any thread or process that is suspended
for (IExecutionDMContext execDmc : execDmcSuspendedList) {
if (isSuspended(execDmc)) {
rm.done(true);
return;
}
}
// Didn't find anything that was suspended.
rm.done(false);
}
/** @since 4.1 */
@Override
public void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
assert contexts != null;
List<IExecutionDMContext> execDmcSuspendedList = extractContextsForOperation(contexts);
// Look for any thread or process that is not suspended
for (IExecutionDMContext execDmc : execDmcSuspendedList) {
if (!isSuspended(execDmc)) {
rm.done(false);
return;
}
}
// Everything is suspended.
rm.done(true);
}
/**
* {@inheritDoc}
*
* For GDB, a separate suspend command will be sent, one for each context
* that can be suspended.
* @since 4.1
*/
@Override
public void suspend(IExecutionDMContext[] contexts, RequestMonitor rm) {
assert contexts != null;
List<IExecutionDMContext> execDmcToSuspendList = extractContextsForOperation(contexts);
CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm);
int count = 0;
// Perform resume operation on each thread or process that can be resumed
for (IExecutionDMContext execDmc : execDmcToSuspendList) {
if (doCanSuspend(execDmc)) {
count++;
suspend(execDmc, crm);
}
}
crm.setDoneCount(count);
}
///////////////////////////////////////////////////////////////////////////
// Multi-step implementation. Not implemented yet. See bug 330974.
///////////////////////////////////////////////////////////////////////////
/** @since 4.1 */
@Override
public void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor<Boolean> rm) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
}
/** @since 4.1 */
@Override
public void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor<Boolean> rm) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
}
/** @since 4.1 */
@Override
public void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
}
/** @since 4.1 */
@Override
public void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
}
/** @since 4.1 */
@Override
public void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm) {
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
}
/**
* Removes duplicates from the list of execution contexts, in case the same thread
* or process is present more than once.
*
* Also, remove any thread that is part of a process that is also present. This is
* because an operation on the process will affect all its threads anyway.
*/
private List<IExecutionDMContext> extractContextsForOperation(IExecutionDMContext[] contexts) {
// Remove duplicate contexts by using a set
Set<IExecutionDMContext> specifiedExedDmcSet = new HashSet<IExecutionDMContext>(Arrays.asList(contexts));
// A list that ignores threads for which the process is also present
List<IExecutionDMContext> execDmcForOperationList = new ArrayList<IExecutionDMContext>(specifiedExedDmcSet.size());
// Check for the case of a process selected along with some of its threads
for (IExecutionDMContext execDmc : specifiedExedDmcSet) {
if (execDmc instanceof IContainerDMContext) {
// This is a process: it is automatically part of our list
execDmcForOperationList.add(execDmc);
} else {
// Get the process for this thread
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class);
// Check if that process is also present
if (specifiedExedDmcSet.contains(containerDmc) == false) {
// This thread does not belong to a process that is selected, so we keep it.
execDmcForOperationList.add(execDmc);
}
}
}
return execDmcForOperationList;
}
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2011 Ericsson and others. * Copyright (c) 2011, 2012 Ericsson and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -18,6 +18,7 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IMultiRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl2; import org.eclipse.cdt.dsf.debug.service.IRunControl2;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
@ -72,6 +73,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS
register(new String[]{ IRunControl.class.getName(), register(new String[]{ IRunControl.class.getName(),
IRunControl2.class.getName(), IRunControl2.class.getName(),
IMIRunControl.class.getName(), IMIRunControl.class.getName(),
IMultiRunControl.class.getName(),
GDBRunControl_7_0_NS.class.getName(), GDBRunControl_7_0_NS.class.getName(),
GDBRunControl_7_2_NS.class.getName(), GDBRunControl_7_2_NS.class.getName(),
}, },

View file

@ -0,0 +1,76 @@
#ifdef __MINGW32__
#include <process.h> // MinGW has no POSIX support; use MSVC runtime
#else
#include <pthread.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "Sleep.h"
#ifdef __MINGW32__
typedef unsigned int TID;
#else
typedef pthread_t TID;
#endif
// Set a breakpoint here so that both threads stop.
void firstBreakpoint(int id)
{
printf("First breakpoint method from thread %d\n", id);
}
#ifdef __MINGW32__
unsigned int __stdcall PrintHello(void *threadid)
#else
void *PrintHello(void *threadId)
#endif
{
int tId = (int)threadId;
firstBreakpoint(tId); // Stop a first time
SLEEP(1); // Keep state running a little
firstBreakpoint(tId); // Stop a second time
SLEEP(3); // Resuming past this will give us a running thread
#ifdef __MINGW32__
return 0;
#else
pthread_exit(NULL);
#endif
}
int main(int argc, char *argv[])
{
TID thread;
int tId = 1; // Break at main will stop here: we have a single thread stopped
SLEEP(1); // When resuming past here, we have a single thread running
#ifdef __MINGW32__
uintptr_t rc = _beginthreadex(NULL, 0, PrintHello, (void*)tId, 0, &thread);
if (rc == 0)
{
printf("ERROR; _beginthreadex() failed. errno = %d\n", errno);
exit(-1);
}
#else
int rc = pthread_create(&thread, NULL, PrintHello, (void *)tId);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
#endif
firstBreakpoint(0);
SLEEP(1); // Resuming past this will make this thread run, while we stop the second thread
SLEEP(3); // Resuming past this will make this thread run, while we also run the second thread
return 0;
}

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2007, 2010 Ericsson and others. * Copyright (c) 2007, 2012 Ericsson and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,9 +7,13 @@
* *
* Contributors: * Contributors:
* Ericsson - Initial Implementation * Ericsson - Initial Implementation
* Marc Khouzam (Ericsson) - Add support to receive multiple events
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.framework; package org.eclipse.cdt.tests.dsf.gdb.framework;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
@ -17,7 +21,7 @@ import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin; import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
/* /**
* This class provides a way to wait for an asynchronous ServerEvent * This class provides a way to wait for an asynchronous ServerEvent
* to occur. The user of this class specifies which event is of * to occur. The user of this class specifies which event is of
* interest . waitForEvent() can then be called to block until the event occurs or * interest . waitForEvent() can then be called to block until the event occurs or
@ -40,7 +44,9 @@ public class ServiceEventWaitor<V> {
/* The type of event to wait for */ /* The type of event to wait for */
private Class<V> fEventTypeClass; private Class<V> fEventTypeClass;
private DsfSession fSession; private DsfSession fSession;
private V fEvent;
// Queue of events. This allows to receive multiple events and keep them.
private List<V> fEventQueue = Collections.synchronizedList(new LinkedList<V>());
/** /**
* Trace option for wait metrics * Trace option for wait metrics
@ -59,7 +65,6 @@ public class ServiceEventWaitor<V> {
assert eventClass != null; assert eventClass != null;
fSession = session; fSession = session;
fEventTypeClass = eventClass; fEventTypeClass = eventClass;
fEvent = null;
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
@ -102,10 +107,9 @@ public class ServiceEventWaitor<V> {
long startMs = System.currentTimeMillis(); long startMs = System.currentTimeMillis();
// The event might have already been received if (fEventQueue.isEmpty()) {
if (fEvent == null) {
wait(timeout); wait(timeout);
if (fEvent == null) { if (fEventQueue.isEmpty()) {
throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName()); throw new Exception("Timed out waiting for ServiceEvent: " + fEventTypeClass.getName());
} }
} }
@ -159,14 +163,7 @@ public class ServiceEventWaitor<V> {
} }
} }
// Mark that we have consumed the event. return fEventQueue.remove(0);
// This will allow to wait for the next similar event.
// For example, for a restart, there could be more than one
// stopped event, and we need to wait for the second one.
V event = fEvent;
fEvent = null;
return event;
} }
/* /*
@ -177,7 +174,7 @@ public class ServiceEventWaitor<V> {
public void eventDispatched(V event) { public void eventDispatched(V event) {
if (fEventTypeClass.isAssignableFrom(event.getClass())) { if (fEventTypeClass.isAssignableFrom(event.getClass())) {
synchronized(this) { synchronized(this) {
fEvent = event; fEventQueue.add(event);
notifyAll(); notifyAll();
} }
} }

View file

@ -593,17 +593,17 @@ public class SyncUtil {
} }
/** /**
* Utility method to return the execution DM context. * Utility method to return all thread execution contexts.
*/ */
@ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()") @ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()")
public static IMIExecutionDMContext getExecutionContext(final int threadIndex) throws InterruptedException { public static IMIExecutionDMContext[] getExecutionContexts() throws InterruptedException {
assert !fProcessesService.getExecutor().isInExecutorThread(); assert !fProcessesService.getExecutor().isInExecutorThread();
final IContainerDMContext containerDmc = SyncUtil.getContainerContext(); final IContainerDMContext containerDmc = SyncUtil.getContainerContext();
Query<IMIExecutionDMContext> query = new Query<IMIExecutionDMContext>() { Query<IMIExecutionDMContext[]> query = new Query<IMIExecutionDMContext[]>() {
@Override @Override
protected void execute(final DataRequestMonitor<IMIExecutionDMContext> rm) { protected void execute(final DataRequestMonitor<IMIExecutionDMContext[]> rm) {
fProcessesService.getProcessesBeingDebugged( fProcessesService.getProcessesBeingDebugged(
containerDmc, containerDmc,
new ImmediateDataRequestMonitor<IDMContext[]>() { new ImmediateDataRequestMonitor<IDMContext[]>() {
@ -612,10 +612,7 @@ public class SyncUtil {
if (isSuccess()) { if (isSuccess()) {
IDMContext[] threads = getData(); IDMContext[] threads = getData();
Assert.assertNotNull("invalid return value from service", threads); Assert.assertNotNull("invalid return value from service", threads);
Assert.assertTrue("unexpected number of threads", threadIndex < threads.length); rm.setData((IMIExecutionDMContext[])threads);
IDMContext thread = threads[threadIndex];
Assert.assertNotNull("unexpected thread context type ", thread);
rm.setData((IMIExecutionDMContext)thread);
} else { } else {
rm.setStatus(getStatus()); rm.setStatus(getStatus());
} }
@ -633,6 +630,16 @@ public class SyncUtil {
} }
return null; return null;
} }
/**
* Utility method to return a specific execution DM context.
*/
@ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()")
public static IMIExecutionDMContext getExecutionContext(int threadIndex) throws InterruptedException {
IMIExecutionDMContext[] threads = getExecutionContexts();
Assert.assertTrue("unexpected number of threads", threadIndex < threads.length);
Assert.assertNotNull("unexpected thread context type ", threads[threadIndex]);
return threads[threadIndex];
}
/** /**
* Check if the restart operation is supported * Check if the restart operation is supported

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class,
PostMortemCoreTest_7_0.class, PostMortemCoreTest_7_0.class,
CommandTimeoutTest_7_0.class, CommandTimeoutTest_7_0.class,
GDBMultiNonStopRunControlTest_7_0.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningTest_7_0.class, OperationsWhileTargetIsRunningTest_7_0.class,
OperationsWhileTargetIsRunningNonStopTest_7_0.class, OperationsWhileTargetIsRunningNonStopTest_7_0.class,
CommandTimeoutTest_7_0.class, CommandTimeoutTest_7_0.class,
GDBMultiNonStopRunControlTest_7_0.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson 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:
* Marc Khouzam (Ericsson) - Initial implementation of Test cases
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_0.GDBMultiNonStopRunControlTest_7_0;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
/**
* Tests IMultiRunControl class for Non-stop multi-threaded application.
*/
@RunWith(BackgroundRunner.class)
public class GDBMultiNonStopRunControlTest_7_1 extends GDBMultiNonStopRunControlTest_7_0 {
@BeforeClass
public static void beforeClassMethod_7_1() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_1);
}
}

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class,
PostMortemCoreTest_7_1.class, PostMortemCoreTest_7_1.class,
CommandTimeoutTest_7_1.class, CommandTimeoutTest_7_1.class,
GDBMultiNonStopRunControlTest_7_1.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningTest_7_1.class, OperationsWhileTargetIsRunningTest_7_1.class,
OperationsWhileTargetIsRunningNonStopTest_7_1.class, OperationsWhileTargetIsRunningNonStopTest_7_1.class,
CommandTimeoutTest_7_1.class, CommandTimeoutTest_7_1.class,
GDBMultiNonStopRunControlTest_7_1.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson 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:
* Marc Khouzam (Ericsson) - Initial implementation of Test cases
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_1.GDBMultiNonStopRunControlTest_7_1;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
/**
* Tests IMultiRunControl class for Non-stop multi-threaded application.
*/
@RunWith(BackgroundRunner.class)
public class GDBMultiNonStopRunControlTest_7_2 extends GDBMultiNonStopRunControlTest_7_1 {
@BeforeClass
public static void beforeClassMethod_7_2() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_2);
}
}

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class,
PostMortemCoreTest_7_2.class, PostMortemCoreTest_7_2.class,
CommandTimeoutTest_7_2.class, CommandTimeoutTest_7_2.class,
GDBMultiNonStopRunControlTest_7_2.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningTest_7_2.class, OperationsWhileTargetIsRunningTest_7_2.class,
OperationsWhileTargetIsRunningNonStopTest_7_2.class, OperationsWhileTargetIsRunningNonStopTest_7_2.class,
CommandTimeoutTest_7_2.class, CommandTimeoutTest_7_2.class,
GDBMultiNonStopRunControlTest_7_2.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson 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:
* Marc Khouzam (Ericsson) - Initial implementation of Test cases
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_2.GDBMultiNonStopRunControlTest_7_2;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
/**
* Tests IMultiRunControl class for Non-stop multi-threaded application.
*/
@RunWith(BackgroundRunner.class)
public class GDBMultiNonStopRunControlTest_7_3 extends GDBMultiNonStopRunControlTest_7_2 {
@BeforeClass
public static void beforeClassMethod_7_3() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_3);
}
}

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class,
PostMortemCoreTest_7_3.class, PostMortemCoreTest_7_3.class,
CommandTimeoutTest_7_3.class, CommandTimeoutTest_7_3.class,
GDBMultiNonStopRunControlTest_7_3.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningTest_7_3.class, OperationsWhileTargetIsRunningTest_7_3.class,
OperationsWhileTargetIsRunningNonStopTest_7_3.class, OperationsWhileTargetIsRunningNonStopTest_7_3.class,
CommandTimeoutTest_7_3.class, CommandTimeoutTest_7_3.class,
GDBMultiNonStopRunControlTest_7_3.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson 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:
* Marc Khouzam (Ericsson) - Initial implementation of Test cases
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_4;
import org.eclipse.cdt.tests.dsf.gdb.framework.BackgroundRunner;
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
import org.eclipse.cdt.tests.dsf.gdb.tests.tests_7_3.GDBMultiNonStopRunControlTest_7_3;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
/**
* Tests IMultiRunControl class for Non-stop multi-threaded application.
*/
@RunWith(BackgroundRunner.class)
public class GDBMultiNonStopRunControlTest_7_4 extends GDBMultiNonStopRunControlTest_7_3 {
@BeforeClass
public static void beforeClassMethod_7_4() {
setGdbProgramNamesLaunchAttributes(ITestConstants.SUFFIX_GDB_7_4);
}
}

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningNonStopTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class,
PostMortemCoreTest_7_4.class, PostMortemCoreTest_7_4.class,
CommandTimeoutTest_7_4.class, CommandTimeoutTest_7_4.class,
GDBMultiNonStopRunControlTest_7_4.class,
Suite_Sessionless_Tests.class, Suite_Sessionless_Tests.class,
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -41,6 +41,7 @@ import org.junit.runners.Suite;
OperationsWhileTargetIsRunningTest_7_4.class, OperationsWhileTargetIsRunningTest_7_4.class,
OperationsWhileTargetIsRunningNonStopTest_7_4.class, OperationsWhileTargetIsRunningNonStopTest_7_4.class,
CommandTimeoutTest_7_4.class, CommandTimeoutTest_7_4.class,
GDBMultiNonStopRunControlTest_7_4.class,
Suite_Sessionless_Tests.class Suite_Sessionless_Tests.class
/* Add your test class here */ /* Add your test class here */
}) })

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2009 Wind River Systems and others. * Copyright (c) 2006, 2012 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,9 +7,13 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Marc Khouzam (Ericsson) - Added support for multiple selection (bug 330974)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.actions; package org.eclipse.cdt.dsf.debug.ui.actions;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.DMContexts;
@ -29,11 +33,18 @@ import org.eclipse.debug.core.commands.IDebugCommandRequest;
*/ */
@Immutable @Immutable
public abstract class DsfCommandRunnable extends DsfRunnable { public abstract class DsfCommandRunnable extends DsfRunnable {
private final IExecutionDMContext fContext; private final IExecutionDMContext[] fContexts;
private final DsfServicesTracker fTracker; private final DsfServicesTracker fTracker;
private final IDebugCommandRequest fRequest; private final IDebugCommandRequest fRequest;
public IExecutionDMContext getContext() { return fContext; } // For backwards compatibility, keep this method that returns the first selection. This method
// is meaningful when we only support a single selection.
public IExecutionDMContext getContext() { return (fContexts != null && fContexts.length > 0) ? fContexts[0] : null; }
/**
* Return all selected contexts.
* @since 2.3
*/
public IExecutionDMContext[] getContexts() { return fContexts; }
public IRunControl getRunControl() { public IRunControl getRunControl() {
return fTracker.getService(IRunControl.class); return fTracker.getService(IRunControl.class);
} }
@ -42,8 +53,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable {
* @since 1.1 * @since 1.1
*/ */
public SteppingController getSteppingController() { public SteppingController getSteppingController() {
if (fContext != null) { if (fContexts != null && fContexts.length > 0) {
return (SteppingController) fContext.getAdapter(SteppingController.class); return (SteppingController) fContexts[0].getAdapter(SteppingController.class);
} }
return null; return null;
} }
@ -56,15 +67,33 @@ public abstract class DsfCommandRunnable extends DsfRunnable {
} }
public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) { public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) {
fTracker = servicesTracker; this(servicesTracker, new Object[] { element }, request);
if (element instanceof IDMVMContext) { }
IDMVMContext vmc = (IDMVMContext)element;
fContext = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
} else {
fContext = null;
}
fRequest = request; /** @since 2.3 */
public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object[] elements, IDebugCommandRequest request) {
fTracker = servicesTracker;
fRequest = request;
// Extract all selected execution contexts, using a set to avoid duplicates. Duplicates will
// happen if multiple stack frames of the same thread are selected.
Set<IExecutionDMContext> execDmcSet = new HashSet<IExecutionDMContext>(request.getElements().length);
for (Object element : request.getElements()) {
if (element instanceof IDMVMContext) {
IDMVMContext vmc = (IDMVMContext)element;
IExecutionDMContext execDmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
if (execDmc != null) {
// We have a thread or a process
execDmcSet.add(execDmc);
}
}
}
if (execDmcSet.size() == 0) {
fContexts = null;
} else {
fContexts = execDmcSet.toArray(new IExecutionDMContext[execDmcSet.size()]);
}
} }
@Override @Override
@ -73,8 +102,8 @@ public abstract class DsfCommandRunnable extends DsfRunnable {
fRequest.done(); fRequest.done();
return; return;
} }
if (getContext() == null) { if (getContexts() == null || getContexts().length == 0) {
fRequest.setStatus(makeError("Selected object does not support run control.", null)); //$NON-NLS-1$ fRequest.setStatus(makeError("Selected objects do not support run control.", null)); //$NON-NLS-1$
} else if (getRunControl() == null || getSteppingController() == null) { } else if (getRunControl() == null || getSteppingController() == null) {
fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$ fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$
} else { } else {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2009 Wind River Systems and others. * Copyright (c) 2006, 2012 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,14 +7,16 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.actions; package org.eclipse.cdt.dsf.debug.ui.actions;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.IMultiRunControl;
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.service.DsfSession;
@ -43,17 +45,42 @@ public class DsfResumeCommand implements IResumeHandler {
@Override @Override
public void canExecute(final IEnabledStateRequest request) { public void canExecute(final IEnabledStateRequest request) {
if (request.getElements().length != 1) { if (request.getElements().length == 1) {
request.setEnabled(false); canExecuteSingle(request);
request.done();
return; return;
} }
// Handle multi-selection
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) {
@Override public void doExecute() {
final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class);
if (multiRun == null) {
// No multi run control service: multi selection not allowed
request.setEnabled(false);
request.done();
return;
}
// Check if some of the selections can be resumed
multiRun.canResumeSome(
getContexts(),
new ImmediateDataRequestMonitor<Boolean>() {
@Override
protected void handleCompleted() {
request.setEnabled(isSuccess() && getData());
request.done();
}
});
}
});
}
private void canExecuteSingle(final IEnabledStateRequest request) {
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
@Override public void doExecute() { @Override public void doExecute() {
getRunControl().canResume( getRunControl().canResume(
getContext(), getContext(),
new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) { new ImmediateDataRequestMonitor<Boolean>() {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
request.setEnabled(isSuccess() && getData()); request.setEnabled(isSuccess() && getData());
@ -66,17 +93,32 @@ public class DsfResumeCommand implements IResumeHandler {
@Override @Override
public boolean execute(final IDebugCommandRequest request) { public boolean execute(final IDebugCommandRequest request) {
if (request.getElements().length != 1) { if (request.getElements().length == 1) {
request.done(); executeSingle(request);
return false; return false;
} }
// Handle multi-selection
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) {
@Override public void doExecute() {
final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class);
if (multiRun == null) {
// No multi run control service: multi selection not allowed
request.done();
return;
}
multiRun.resume(getContexts(), new ImmediateRequestMonitor());
}
});
return false;
}
private void executeSingle(IDebugCommandRequest request) {
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
@Override public void doExecute() { @Override public void doExecute() {
getRunControl().resume(getContext(), new RequestMonitor(fExecutor, null)); getRunControl().resume(getContext(), new RequestMonitor(fExecutor, null));
} }
}); });
return false;
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2006, 2009 Wind River Systems and others. * Copyright (c) 2006, 2012 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -7,14 +7,16 @@
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
* Marc Khouzam (Ericsson) - Added support for multi-selection (Bug 330974)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.actions; package org.eclipse.cdt.dsf.debug.ui.actions;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.IMultiRunControl;
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.service.DsfSession;
@ -42,17 +44,42 @@ public class DsfSuspendCommand implements ISuspendHandler {
@Override @Override
public void canExecute(final IEnabledStateRequest request) { public void canExecute(final IEnabledStateRequest request) {
if (request.getElements().length != 1) { if (request.getElements().length == 1) {
request.setEnabled(false); canExecuteSingle(request);
request.done();
return; return;
} }
// Handle multi-selection
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) {
@Override public void doExecute() {
final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class);
if (multiRun == null) {
// No multi run control service: multi selection not allowed
request.setEnabled(false);
request.done();
return;
}
// Check if some of the selections can be suspended
multiRun.canSuspendSome(
getContexts(),
new ImmediateDataRequestMonitor<Boolean>() {
@Override
protected void handleCompleted() {
request.setEnabled(isSuccess() && getData());
request.done();
}
});
}
});
}
private void canExecuteSingle(final IEnabledStateRequest request) {
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
@Override public void doExecute() { @Override public void doExecute() {
getRunControl().canSuspend( getRunControl().canSuspend(
getContext(), getContext(),
new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) { new ImmediateDataRequestMonitor<Boolean>() {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
request.setEnabled(isSuccess() && getData()); request.setEnabled(isSuccess() && getData());
@ -65,17 +92,32 @@ public class DsfSuspendCommand implements ISuspendHandler {
@Override @Override
public boolean execute(final IDebugCommandRequest request) { public boolean execute(final IDebugCommandRequest request) {
if (request.getElements().length != 1) { if (request.getElements().length == 1) {
request.done(); executeSingle(request);
return false; return false;
} }
// Handle multi-selection
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements(), request) {
@Override public void doExecute() {
final IMultiRunControl multiRun = fTracker.getService(IMultiRunControl.class);
if (multiRun == null) {
// No multi run control service: multi selection not allowed
request.done();
return;
}
multiRun.suspend(getContexts(), new ImmediateRequestMonitor());
}
});
return false;
}
private void executeSingle(IDebugCommandRequest request) {
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) { fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
@Override public void doExecute() { @Override public void doExecute() {
getRunControl().suspend(getContext(), new RequestMonitor(fExecutor, null)); getRunControl().suspend(getContext(), new RequestMonitor(fExecutor, null));
} }
}); });
return false;
} }
} }

View file

@ -0,0 +1,134 @@
/*******************************************************************************
* Copyright (c) 2012 Ericsson 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:
* Marc Khouzam (Ericsson) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.service;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
/**
* This interface provides the ability to perform run control operations on multiple contexts.
*
* @see org.eclipse.cdt.dsf.debug.service.IRunControl
*
* @since 2.3
*/
public interface IMultiRunControl extends IRunControl
{
/**
* Check if at least one of the specified contexts can be resumed
* @param context List of execution contexts that want to be resumed
* @param rm Request monitor returning:
* true if at least one of the specified contexts can be resumed
* false if none of the specified contexts can be resumed
*/
void canResumeSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if all of the specified contexts can be resumed
* @param context List of execution contexts that want to be resumed
* @param rm Request monitor returning:
* true if all of the specified contexts can be resumed
* false if any of the specified contexts cannot be resumed
*/
void canResumeAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if at least one of the specified contexts can be suspended
* @param context List of execution contexts that want to be suspended
* @param rm Request monitor returning:
* true if at least one of the specified contexts can be suspended
* false if none of the specified contexts can be suspended
*/
void canSuspendSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if all of the specified contexts can be suspended
* @param context List of execution contexts that want to be suspended
* @param rm Request monitor returning:
* true if all of the specified contexts can be suspended
* false if any of the specified contexts cannot be suspended
*/
void canSuspendAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if any of the specified contexts is suspended.
* @param context List of execution contexts that are to be checked for being suspended
* @param rm Request monitor returning:
* true if any of the specified contexts is suspended, false otherwise
*/
void isSuspendedSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if all of the specified contexts are suspended.
* @param context List of execution contexts that are to be checked for being suspended
* @param rm Request monitor returning:
* true if all of the specified contexts are suspended, false otherwise
*/
void isSuspendedAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if any of the specified contexts can be stepped using stepType
* @param context List of execution contexts that want to be stepped
* @param stepStype The type of step to be used.
* @param rm Request monitor returning:
* true if any of the specified contexts can be stepped
* false if none of the specified contexts can be stepped
*/
void canStepSome(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor<Boolean> rm);
/**
* Check if all of the specified contexts can be stepped using stepType
* @param context List of execution contexts that want to be stepped
* @param stepStype The type of step to be used.
* @param rm Request monitor returning:
* true if all of the specified contexts can be stepped
* false if any of the specified contexts cannot be stepped
*/
void canStepAll(IExecutionDMContext[] contexts, StepType stepType, DataRequestMonitor<Boolean> rm);
/**
* Check if any of the specified contexts is currently stepping.
* @param context List of execution contexts that are to be checked for stepping
* @param rm Request monitor returning:
* true if any of the specified contexts is stepping, false otherwise
*/
void isSteppingSome(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Check if all of the specified contexts are currently stepping.
* @param context List of execution contexts that are to be checked for stepping
* @param rm Request monitor returning:
* true if all of the specified contexts are stepping, false otherwise
*/
void isSteppingAll(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Request that all specified contexts be resumed. Only contexts that are in a
* state that can be resumed will be affected, others will be ignored.
* @param context List of execution contexts that are to be resumed
*/
void resume(IExecutionDMContext[] contexts, RequestMonitor rm);
/**
* Request that all specified contexts be suspended. Only contexts that are in a
* state that can be suspended will be affected, others will be ignored.
* @param context List of execution contexts that are to be suspended
*/
void suspend(IExecutionDMContext[] contexts, RequestMonitor rm);
/**
* Request that all specified context be stepped using stepType. Only contexts
* that are in a state that can be stepped will be affected, others will be ignored.
* @param context List of execution contexts that are to be stepped
* @param stepStype The type of step to be used.
*/
void step(IExecutionDMContext[] contexts, StepType stepType, RequestMonitor rm);
}