mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +02:00
Redo the event dispatch now a permanent thread is use to
dispatch events.
This commit is contained in:
parent
b8c5ededb8
commit
1354f9e661
21 changed files with 312 additions and 183 deletions
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* (c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
package org.eclipse.cdt.debug.mi.core;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.debug.mi.core.command.Command;
|
||||
|
||||
/**
|
||||
* Simple thread-safe Queue implemetation.
|
||||
*/
|
||||
public class CommandQueue extends Queue{
|
||||
|
||||
|
||||
public CommandQueue() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Command removeCommand(int id) {
|
||||
//print("in removeCommand(" + id + ") - entering");
|
||||
synchronized (list) {
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Command cmd = (Command)list.get(i);
|
||||
int token = cmd.getToken();
|
||||
if (token == id) {
|
||||
list.remove(cmd);
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Command removeCommand() throws InterruptedException {
|
||||
//print("in removeCommand() - entering");
|
||||
return (Command)removeItem();
|
||||
}
|
||||
|
||||
public void addCommand(Command cmd) {
|
||||
//print("in addCommand() - entering");
|
||||
addItem(cmd);
|
||||
}
|
||||
|
||||
private static void print(String msg) {
|
||||
String name = Thread.currentThread().getName();
|
||||
System.out.println(name + ": " + msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* (c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.eclipse.cdt.debug.mi.core;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
|
||||
|
||||
/**
|
||||
* Transmission command thread blocks on the command Queue
|
||||
* and wake cmd are available and push them to gdb out channel.
|
||||
*/
|
||||
public class EventThread extends Thread {
|
||||
|
||||
MISession session;
|
||||
|
||||
public EventThread(MISession s) {
|
||||
super("MI Event Thread");
|
||||
session = s;
|
||||
}
|
||||
|
||||
public void run () {
|
||||
try {
|
||||
while (true) {
|
||||
MIEvent event = null;
|
||||
Queue eventQueue = session.getEventQueue();
|
||||
// removeItem() will block until an item is available.
|
||||
try {
|
||||
event = (MIEvent)eventQueue.removeItem();
|
||||
} catch (InterruptedException e) {
|
||||
// signal by the session of time to die.
|
||||
if (session.getChannelOutputStream() == null) {
|
||||
throw new IOException();
|
||||
}
|
||||
//e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
session.notifyObservers(event);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import org.eclipse.cdt.debug.mi.core.command.CLICommand;
|
|||
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIExecAbort;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBShowExitCode;
|
||||
import org.eclipse.cdt.debug.mi.core.event.MIInferiorExitEvent;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo;
|
||||
|
||||
/**
|
||||
|
@ -18,7 +19,7 @@ import org.eclipse.cdt.debug.mi.core.output.MIGDBShowExitCodeInfo;
|
|||
* To enable and disable the creation of type comments go to
|
||||
* Window>Preferences>Java>Code Generation.
|
||||
*/
|
||||
public class MIProcess extends Process {
|
||||
public class MIInferior extends Process {
|
||||
|
||||
public final static int SUSPENDED = 1;
|
||||
public final static int RUNNING = 2;
|
||||
|
@ -29,7 +30,7 @@ public class MIProcess extends Process {
|
|||
MISession session;
|
||||
OutputStream out;
|
||||
|
||||
MIProcess(MISession mi) {
|
||||
MIInferior(MISession mi) {
|
||||
session = mi;
|
||||
out = new OutputStream() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
@ -39,6 +40,8 @@ public class MIProcess extends Process {
|
|||
flush();
|
||||
}
|
||||
}
|
||||
// Encapsulate the string sent to gdb in a fake command.
|
||||
// and post it to the TxThread.
|
||||
public void flush() throws IOException {
|
||||
CLICommand cmd = new CLICommand(buf.toString()) {
|
||||
public void setToken(int token) {
|
||||
|
@ -113,16 +116,13 @@ public class MIProcess extends Process {
|
|||
if (!isTerminated()) {
|
||||
CommandFactory factory = session.getCommandFactory();
|
||||
MIExecAbort abort = factory.createMIExecAbort();
|
||||
CLICommand yes = new CLICommand("yes") {
|
||||
public void setToken() { }
|
||||
};
|
||||
try {
|
||||
session.postCommand(abort);
|
||||
session.postCommand(yes);
|
||||
setTerminated();
|
||||
session.getRxThread().fireEvent(new MIInferiorExitEvent());
|
||||
} catch (MIException e) {
|
||||
}
|
||||
}
|
||||
// Do not wait for answer.
|
||||
}
|
||||
|
||||
public synchronized boolean isSuspended() {
|
|
@ -48,7 +48,7 @@ public class MIPlugin extends Plugin {
|
|||
}
|
||||
|
||||
public ICDISession createCSession(String program) throws IOException {
|
||||
String[]args = new String[]{"gdb", "--quiet", "-i", "mi", program};
|
||||
String[]args = new String[]{"gdb", "-q", "-i", "mi", program};
|
||||
Process gdb = Runtime.getRuntime().exec(args);
|
||||
MISession session = createMISession(gdb.getInputStream(), gdb.getOutputStream());
|
||||
/*
|
||||
|
|
|
@ -13,6 +13,8 @@ import java.util.Observable;
|
|||
|
||||
import org.eclipse.cdt.debug.mi.core.command.Command;
|
||||
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBExit;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIGDBSet;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIOutput;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIParser;
|
||||
|
||||
|
@ -27,11 +29,13 @@ public class MISession extends Observable {
|
|||
InputStream inChannel;
|
||||
OutputStream outChannel;
|
||||
|
||||
Thread txThread;
|
||||
Thread rxThread;
|
||||
TxThread txThread;
|
||||
RxThread rxThread;
|
||||
EventThread eventThread;
|
||||
|
||||
Queue txQueue;
|
||||
Queue rxQueue;
|
||||
CommandQueue txQueue;
|
||||
CommandQueue rxQueue;
|
||||
Queue eventQueue;
|
||||
|
||||
PipedInputStream miInPipe;
|
||||
PipedOutputStream miOutPipe;
|
||||
|
@ -46,7 +50,7 @@ public class MISession extends Observable {
|
|||
|
||||
long cmdTimeout = 10000; // 10 * 1000 (~ 10 secs);
|
||||
|
||||
MIProcess process;
|
||||
MIInferior inferior;
|
||||
|
||||
/**
|
||||
* Create the gdb session.
|
||||
|
@ -59,12 +63,15 @@ public class MISession extends Observable {
|
|||
outChannel = o;
|
||||
factory = new CommandFactory();
|
||||
parser = new MIParser();
|
||||
txQueue = new Queue();
|
||||
rxQueue = new Queue();
|
||||
txQueue = new CommandQueue();
|
||||
rxQueue = new CommandQueue();
|
||||
eventQueue = new Queue();
|
||||
txThread = new TxThread(this);
|
||||
rxThread = new RxThread(this);
|
||||
eventThread = new EventThread(this);
|
||||
txThread.start();
|
||||
rxThread.start();
|
||||
eventThread.start();
|
||||
|
||||
try {
|
||||
miOutPipe = new PipedOutputStream();
|
||||
|
@ -76,7 +83,11 @@ public class MISession extends Observable {
|
|||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
process = new MIProcess(this);
|
||||
inferior = new MIInferior(this);
|
||||
try {
|
||||
postCommand(new MIGDBSet(new String[]{"confirm", "off"}));
|
||||
} catch (MIException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,25 +168,35 @@ public class MISession extends Observable {
|
|||
public void postCommand(Command cmd, long timeout) throws MIException {
|
||||
|
||||
MIPlugin.getDefault().debugLog(cmd.toString());
|
||||
|
||||
// Test if we in a sane state.
|
||||
if (!txThread.isAlive() || !rxThread.isAlive()) {
|
||||
throw new MIException("{R,T}xThread terminated");
|
||||
}
|
||||
|
||||
txQueue.addCommand(cmd);
|
||||
|
||||
// Wait for the response or timedout
|
||||
synchronized (cmd) {
|
||||
// RxThread will set the MIOutput on the cmd
|
||||
// when the response arrive.
|
||||
while (cmd.getMIOutput() == null) {
|
||||
try {
|
||||
cmd.wait(timeout);
|
||||
break; // Timeout or Notify
|
||||
} catch (InterruptedException e) {
|
||||
// Do not wait for command if time out is 0
|
||||
if (timeout > 0) {
|
||||
// RxThread will set the MIOutput on the cmd
|
||||
// when the response arrive.
|
||||
while (cmd.getMIOutput() == null) {
|
||||
try {
|
||||
cmd.wait(timeout);
|
||||
if (cmd.getMIOutput() == null) {
|
||||
throw new MIException("Timedout");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MIProcess getMIProcess() {
|
||||
return process;
|
||||
public MIInferior getMIInferior() {
|
||||
return inferior;
|
||||
}
|
||||
|
||||
public boolean isTerminated() {
|
||||
|
@ -187,9 +208,17 @@ public class MISession extends Observable {
|
|||
*/
|
||||
public void terminate() {
|
||||
|
||||
process.destroy();
|
||||
// Destroy any MI Inferior
|
||||
inferior.destroy();
|
||||
|
||||
// Closing the channel will kill the RxThread.
|
||||
// send the exit.
|
||||
try {
|
||||
MIGDBExit exit = factory.createMIGDBExit();
|
||||
postCommand(exit);
|
||||
} catch (MIException e) {
|
||||
}
|
||||
|
||||
// Explicitely close the channels
|
||||
try {
|
||||
inChannel.close();
|
||||
} catch (IOException e) {
|
||||
|
@ -200,9 +229,10 @@ public class MISession extends Observable {
|
|||
outChannel.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
// This is __needed__ to stop the txThread.
|
||||
// This is __needed__ to stop the txThread and eventThread.
|
||||
outChannel = null;
|
||||
|
||||
// Make sure all threads are gone.
|
||||
try {
|
||||
if (txThread.isAlive()) {
|
||||
txThread.interrupt();
|
||||
|
@ -218,6 +248,14 @@ public class MISession extends Observable {
|
|||
rxThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (eventThread.isAlive()) {
|
||||
eventThread.interrupt();
|
||||
}
|
||||
eventThread.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,14 +279,22 @@ public class MISession extends Observable {
|
|||
return logOutPipe;
|
||||
}
|
||||
|
||||
Queue getTxQueue() {
|
||||
CommandQueue getTxQueue() {
|
||||
return txQueue;
|
||||
}
|
||||
|
||||
Queue getRxQueue() {
|
||||
CommandQueue getRxQueue() {
|
||||
return rxQueue;
|
||||
}
|
||||
|
||||
Queue getEventQueue() {
|
||||
return eventQueue;
|
||||
}
|
||||
|
||||
RxThread getRxThread() {
|
||||
return rxThread;
|
||||
}
|
||||
|
||||
InputStream getChannelInputStream() {
|
||||
return inChannel;
|
||||
}
|
||||
|
|
|
@ -8,65 +8,47 @@ import java.util.Collections;
|
|||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.debug.mi.core.command.Command;
|
||||
|
||||
/**
|
||||
* Simple thread-safe Queue implemetation.
|
||||
*/
|
||||
public class Queue {
|
||||
|
||||
private List list;
|
||||
protected List list;
|
||||
|
||||
public Queue() {
|
||||
list = Collections.synchronizedList(new LinkedList());
|
||||
}
|
||||
|
||||
public Command removeCommand(int id) {
|
||||
//print("in removeCommand(" + id + ") - entering");
|
||||
synchronized (list) {
|
||||
int size = list.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
Command cmd = (Command)list.get(i);
|
||||
int token = cmd.getToken();
|
||||
if (token == id) {
|
||||
list.remove(cmd);
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Command removeCommand() throws InterruptedException {
|
||||
//print("in removeCommand() - entering");
|
||||
public Object removeItem() throws InterruptedException {
|
||||
//print("in removeItem() - entering");
|
||||
synchronized (list) {
|
||||
while (list.isEmpty()) {
|
||||
//print("in removeCommand() - about to wait()");
|
||||
//print("in removeItem() - about to wait()");
|
||||
list.wait();
|
||||
//print("in removeCommand() - done with wait()");
|
||||
//print("in removeItem() - done with wait()");
|
||||
}
|
||||
|
||||
// extract the new first cmd
|
||||
Command cmd = (Command)list.remove(0);
|
||||
Object item = list.remove(0);
|
||||
|
||||
//print("in removeCommand() - leaving");
|
||||
return cmd;
|
||||
//print("in removeItem() - leaving");
|
||||
return item;
|
||||
}
|
||||
}
|
||||
public void addCommand(Command cmd) {
|
||||
//print("in addCommand() - entering");
|
||||
public void addItem(Object item) {
|
||||
//print("in addItem() - entering");
|
||||
synchronized (list) {
|
||||
// There will always be room to add to this List
|
||||
// because it expands as needed.
|
||||
list.add(cmd);
|
||||
//print("in addCommand - just added: '" + cmd + "'");
|
||||
list.add(item);
|
||||
//print("in addItem - just added: '" + cmd + "'");
|
||||
|
||||
// After adding, notify any and all waiting
|
||||
// threads that the list has changed.
|
||||
list.notifyAll();
|
||||
//print("in addCommand() - just notified");
|
||||
//print("in addItem() - just notified");
|
||||
}
|
||||
//print("in addCommand() - leaving");
|
||||
//print("in addItem() - leaving");
|
||||
}
|
||||
|
||||
private static void print(String msg) {
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.eclipse.cdt.debug.mi.core.command.MIExecNextInstruction;
|
|||
import org.eclipse.cdt.debug.mi.core.command.MIExecStep;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIExecStepInstruction;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIExecUntil;
|
||||
import org.eclipse.cdt.debug.mi.core.event.EventThread;
|
||||
import org.eclipse.cdt.debug.mi.core.event.MIBreakpointEvent;
|
||||
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
|
||||
import org.eclipse.cdt.debug.mi.core.event.MIExitEvent;
|
||||
|
@ -68,30 +67,12 @@ public class RxThread extends Thread {
|
|||
while (true) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
// Testing on GNU/Linux where target stream output
|
||||
// is entertwine with MI out,
|
||||
// comment out the if/else below and just use:
|
||||
// processMIOutput(line);
|
||||
// at least for testing.
|
||||
|
||||
// We accumulate until we see the gdb terminator.
|
||||
MIPlugin.getDefault().debugLog(line);
|
||||
if (line.startsWith(MIOutput.terminator)) {
|
||||
// discard termination
|
||||
processMIOutput(buffer.toString());
|
||||
buffer = new StringBuffer();
|
||||
} else if (line.startsWith(MITargetStreamOutput.startTag)) {
|
||||
// Process Target output immediately.
|
||||
processMIOutput(line + "\n");
|
||||
} else {
|
||||
buffer.append(line).append('\n');
|
||||
}
|
||||
processMIOutput(line + "\n");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
MIEvent event = new MIExitEvent();
|
||||
Thread eventTread = new EventThread(session, new MIEvent[]{event});
|
||||
eventTread.start();
|
||||
fireEvent(new MIExitEvent());
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +87,7 @@ MIPlugin.getDefault().debugLog(line);
|
|||
MIOutput response = session.parse(buffer);
|
||||
if (response != null) {
|
||||
List list = new ArrayList();
|
||||
Queue rxQueue = session.getRxQueue();
|
||||
CommandQueue rxQueue = session.getRxQueue();
|
||||
|
||||
// Notify any command waiting for a ResultRecord.
|
||||
MIResultRecord rr = response.getMIResultRecord();
|
||||
|
@ -135,11 +116,11 @@ MIPlugin.getDefault().debugLog(line);
|
|||
} else {
|
||||
type = MIRunningEvent.CONTINUE;
|
||||
}
|
||||
session.getMIProcess().setRunning();
|
||||
session.getMIInferior().setRunning();
|
||||
MIEvent event = new MIRunningEvent(type);
|
||||
fireEvents(new MIEvent[]{event});
|
||||
fireEvent(event);
|
||||
} else if ("exit".equals(state)) {
|
||||
session.getMIProcess().setTerminated();
|
||||
session.getMIInferior().setTerminated();
|
||||
}
|
||||
|
||||
// Notify the waiting command.
|
||||
|
@ -180,11 +161,12 @@ MIPlugin.getDefault().debugLog(line);
|
|||
void processMIOOBRecord(MIAsyncRecord async, List list) {
|
||||
if (async instanceof MIExecAsyncOutput) {
|
||||
MIExecAsyncOutput exec = (MIExecAsyncOutput)async;
|
||||
MIEvent e = null;
|
||||
|
||||
// Change of state.
|
||||
String state = exec.getAsyncClass();
|
||||
if ("stopped".equals(state)) {
|
||||
session.getMIProcess().setSuspended();
|
||||
session.getMIInferior().setSuspended();
|
||||
}
|
||||
|
||||
MIResult[] results = exec.getMIResults();
|
||||
|
@ -194,13 +176,22 @@ MIPlugin.getDefault().debugLog(line);
|
|||
if (var.equals("reason")) {
|
||||
if (val instanceof MIConst) {
|
||||
String reason = ((MIConst)val).getString();
|
||||
MIEvent e = createEvent(reason, exec);
|
||||
e = createEvent(reason, exec);
|
||||
if (e != null) {
|
||||
list.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: GDB for temporary breakpoints will not send the
|
||||
// "reason" ??? Fake this as breakpoint-hit
|
||||
if (e == null) {
|
||||
e = createEvent("breakpoint-hit", exec);
|
||||
if (e != null) {
|
||||
list.add(e);
|
||||
}
|
||||
}
|
||||
} else if (async instanceof MIStatusAsyncOutput) {
|
||||
// Nothing done .. but what about +download??
|
||||
} else if (async instanceof MINotifyAsyncOutput) {
|
||||
|
@ -318,19 +309,25 @@ MIPlugin.getDefault().debugLog(line);
|
|||
event = new MIFunctionFinishedEvent(rr);
|
||||
}
|
||||
} else if ("exited-normally".equals(reason)) {
|
||||
session.getMIProcess().setTerminated();
|
||||
session.getMIInferior().setTerminated();
|
||||
event = new MIInferiorExitEvent();
|
||||
} else if ("exited-signalled".equals(reason)) {
|
||||
session.getMIProcess().setTerminated();
|
||||
session.getMIInferior().setTerminated();
|
||||
event = new MIInferiorExitEvent();
|
||||
} else if ("exited".equals(reason)) {
|
||||
session.getMIInferior().setTerminated();
|
||||
event = new MIInferiorExitEvent();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
public void fireEvents(MIEvent[] events) {
|
||||
if (events.length > 0) {
|
||||
Thread eventTread = new EventThread(session, events);
|
||||
eventTread.start();
|
||||
for (int i = 0; i < events.length; i++) {
|
||||
fireEvent(events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void fireEvent(MIEvent event) {
|
||||
session.getEventQueue().addItem(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class TxThread extends Thread {
|
|||
try {
|
||||
while (true) {
|
||||
Command cmd = null;
|
||||
Queue txQueue = session.getTxQueue();
|
||||
CommandQueue txQueue = session.getTxQueue();
|
||||
// removeCommand() will block until a command is available.
|
||||
try {
|
||||
cmd = txQueue.removeCommand();
|
||||
|
@ -54,7 +54,7 @@ public class TxThread extends Thread {
|
|||
// a valid token, this is to permit input(HACK!)
|
||||
// or commands that do not want to wait for responses.
|
||||
if (cmd.getToken() > 0) {
|
||||
Queue rxQueue = session.getRxQueue();
|
||||
CommandQueue rxQueue = session.getRxQueue();
|
||||
rxQueue.addCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,10 @@ import org.eclipse.cdt.debug.mi.core.command.MIExecRun;
|
|||
import org.eclipse.cdt.debug.mi.core.command.MIExecStep;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIExecStepInstruction;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MITargetDetach;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIThreadListIds;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIDataEvaluateExpressionInfo;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIInfo;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIThreadListIdsInfo;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
@ -57,6 +59,16 @@ public class CTarget implements ICDITarget {
|
|||
threadList.remove(cthread);
|
||||
}
|
||||
|
||||
boolean containsCThread(int id) {
|
||||
for (int i = 0; i < threadList.size(); i++) {
|
||||
CThread cthread = (CThread)threadList.get(i);
|
||||
if (cthread.getId() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CThread[] getCThreads() {
|
||||
return (CThread[])threadList.toArray(new CThread[threadList.size()]);
|
||||
}
|
||||
|
@ -109,7 +121,7 @@ public class CTarget implements ICDITarget {
|
|||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#getProcess()
|
||||
*/
|
||||
public Process getProcess() {
|
||||
return session.getMISession().getMIProcess();
|
||||
return session.getMISession().getMIInferior();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,7 +156,29 @@ public class CTarget implements ICDITarget {
|
|||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#getThreads()
|
||||
*/
|
||||
public ICDIThread[] getThreads() throws CDIException {
|
||||
return new ICDIThread[0];
|
||||
MISession mi = session.getMISession();
|
||||
CommandFactory factory = mi.getCommandFactory();
|
||||
MIThreadListIds tids = factory.createMIThreadListIds();
|
||||
try {
|
||||
mi.postCommand(tids);
|
||||
MIThreadListIdsInfo info = tids.getMIThreadListIdsInfo();
|
||||
int[] ids = info.getThreadIds();
|
||||
if (ids != null && ids.length > 0) {
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
if (! containsCThread(ids[i])) {
|
||||
addCThread(new CThread(this, ids[i]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// HACK create a dummy thread
|
||||
if (threadList.size() == 0) {
|
||||
addCThread(new CThread(this, 1));
|
||||
}
|
||||
}
|
||||
} catch (MIException e) {
|
||||
throw new CDIException(e.toString());
|
||||
}
|
||||
return (ICDIThread[])getCThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,21 +192,21 @@ public class CTarget implements ICDITarget {
|
|||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isStepping()
|
||||
*/
|
||||
public boolean isStepping() {
|
||||
return session.getMISession().getMIProcess().isRunning();
|
||||
return session.getMISession().getMIInferior().isRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isSuspended()
|
||||
*/
|
||||
public boolean isSuspended() {
|
||||
return session.getMISession().getMIProcess().isSuspended();
|
||||
return session.getMISession().getMIInferior().isSuspended();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#isTerminated()
|
||||
*/
|
||||
public boolean isTerminated() {
|
||||
return session.getMISession().getMIProcess().isTerminated();
|
||||
return session.getMISession().getMIInferior().isTerminated();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,7 +232,9 @@ public class CTarget implements ICDITarget {
|
|||
*/
|
||||
public void resume() throws CDIException {
|
||||
MISession mi = session.getMISession();
|
||||
if (mi.getMIProcess().isSuspended()) {
|
||||
if (mi.getMIInferior().isRunning() || mi.getMIInferior().isStepping()) {
|
||||
throw new CDIException("Inferior already running");
|
||||
} else if (mi.getMIInferior().isSuspended()) {
|
||||
CommandFactory factory = mi.getCommandFactory();
|
||||
MIExecContinue cont = factory.createMIExecContinue();
|
||||
try {
|
||||
|
@ -210,8 +246,11 @@ public class CTarget implements ICDITarget {
|
|||
} catch (MIException e) {
|
||||
throw new CDIException(e.toString());
|
||||
}
|
||||
} else if (mi.getMIInferior().isTerminated()) {
|
||||
restart();
|
||||
} else {
|
||||
restart();
|
||||
//throw new CDIException("Unknow state");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,7 +348,7 @@ public class CTarget implements ICDITarget {
|
|||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDITarget#terminate()
|
||||
*/
|
||||
public void terminate() throws CDIException {
|
||||
session.getMISession().getMIProcess().destroy();
|
||||
session.getMISession().getMIInferior().destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,9 +6,9 @@ import org.eclipse.cdt.debug.core.cdi.model.ICDIThread;
|
|||
import org.eclipse.cdt.debug.mi.core.MIException;
|
||||
import org.eclipse.cdt.debug.mi.core.MISession;
|
||||
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIStackListFrames;
|
||||
import org.eclipse.cdt.debug.mi.core.command.MIStackListArguments;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIFrame;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIStackListFramesInfo;
|
||||
import org.eclipse.cdt.debug.mi.core.output.MIStackListArgumentsInfo;
|
||||
|
||||
/**
|
||||
* @author alain
|
||||
|
@ -32,7 +32,7 @@ public class CThread extends CObject implements ICDIThread {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
return "thread-" + Integer.toString(id);
|
||||
return Integer.toString(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,10 +48,12 @@ public class CThread extends CObject implements ICDIThread {
|
|||
public ICDIStackFrame[] getStackFrames() throws CDIException {
|
||||
MISession mi = getCTarget().getCSession().getMISession();
|
||||
CommandFactory factory = mi.getCommandFactory();
|
||||
MIStackListFrames frames = factory.createMIStackListFrames();
|
||||
//MIStackListFrames frames = factory.createMIStackListFrames();
|
||||
MIStackListArguments frames = factory.createMIStackListArguments(true);
|
||||
try {
|
||||
mi.postCommand(frames);
|
||||
MIStackListFramesInfo info = frames.getMIStackListFramesInfo();
|
||||
//MIStackListFramesInfo info = frames.getMIStackListFramesInfo();
|
||||
MIStackListArgumentsInfo info = frames.getMIStackListArgumentsInfo();
|
||||
if (info == null) {
|
||||
throw new CDIException("Timedout");
|
||||
}
|
||||
|
|
|
@ -34,12 +34,10 @@ public class EventManager extends SessionObject implements ICDIEventManager {
|
|||
public CDIObserver(ICDIEventListener l) {
|
||||
listener = l;
|
||||
}
|
||||
public void update(Observable o, Object args) {
|
||||
MIEvent[] events = (MIEvent[])args;
|
||||
for (int i = 0; i < events.length; i++) {
|
||||
ICDIEvent cdiEvent = EventAdapter.getCDIEvent(getCSession(), events[i]);
|
||||
listener.handleDebugEvent(cdiEvent);
|
||||
}
|
||||
public void update(Observable o, Object arg) {
|
||||
MIEvent event = (MIEvent)arg;
|
||||
ICDIEvent cdiEvent = EventAdapter.getCDIEvent(getCSession(), event);
|
||||
listener.handleDebugEvent(cdiEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,14 @@ public class Variable extends CObject implements ICDIVariable {
|
|||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getTypeName()
|
||||
*/
|
||||
public String getTypeName() throws CDIException {
|
||||
return null;
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIVariable#getValue()
|
||||
*/
|
||||
public ICDIValue getValue() throws CDIException {
|
||||
return null;
|
||||
return new Value(getCTarget(), arg.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,10 @@ public class MIStackListArguments extends MICommand
|
|||
setParameters(params);
|
||||
}
|
||||
|
||||
public MIStackListArgumentsInfo getMIStackListArgumentsInfo() throws MIException {
|
||||
return (MIStackListArgumentsInfo)getMIInfo();
|
||||
}
|
||||
|
||||
public MIInfo getMIInfo() throws MIException {
|
||||
MIInfo info = null;
|
||||
MIOutput out = getMIOutput();
|
||||
|
|
|
@ -25,6 +25,10 @@ public class MIThreadListIds extends MICommand
|
|||
super("-thread-list-ids");
|
||||
}
|
||||
|
||||
public MIThreadListIdsInfo getMIThreadListIdsInfo() throws MIException {
|
||||
return (MIThreadListIdsInfo)getMIInfo();
|
||||
}
|
||||
|
||||
public MIInfo getMIInfo() throws MIException {
|
||||
MIInfo info = null;
|
||||
MIOutput out = getMIOutput();
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package org.eclipse.cdt.debug.mi.core.event;
|
||||
|
||||
import org.eclipse.cdt.debug.mi.core.MISession;
|
||||
|
||||
/*
|
||||
* (c) Copyright QNX Software Systems Ltd. 2002.
|
||||
* All Rights Reserved.
|
||||
*/
|
||||
|
||||
public class EventThread extends Thread {
|
||||
|
||||
final MISession session;
|
||||
final MIEvent[] events;
|
||||
|
||||
public EventThread(MISession s, MIEvent[] evts) {
|
||||
super("MI Event Thread");
|
||||
session = s;
|
||||
events = evts;
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
public void run () {
|
||||
session.notifyObservers(events);
|
||||
}
|
||||
}
|
|
@ -25,61 +25,38 @@ public class MIDataReadMemoryInfo extends MIInfo {
|
|||
|
||||
public MIDataReadMemoryInfo(MIOutput rr) {
|
||||
super(rr);
|
||||
parse();
|
||||
}
|
||||
|
||||
public long getAddress() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
public long getNumberBytes() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
public long getTotalBytes() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return totalBytes;
|
||||
}
|
||||
|
||||
public long getNextRow() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return nextRow;
|
||||
}
|
||||
|
||||
public long getPreviousRow() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return prevRow;
|
||||
}
|
||||
|
||||
public long getNextPage() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return nextPage;
|
||||
}
|
||||
|
||||
public long getPreviousPage() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return prevPage;
|
||||
}
|
||||
|
||||
public MIMemory[] getMemories() {
|
||||
if (memories == null) {
|
||||
parse();
|
||||
}
|
||||
return memories;
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -116,13 +116,13 @@ public class MIParser {
|
|||
token.delete(0, i);
|
||||
}
|
||||
|
||||
// Process ResultRecord | Out-Of-Band Records
|
||||
// ResultRecord ||| Out-Of-Band Records
|
||||
if (token.length() > 0) {
|
||||
if (token.charAt(0) == '^') {
|
||||
token.deleteCharAt(0);
|
||||
rr = processMIResultRecord(token, id);
|
||||
} else if(token.toString().startsWith(MIOutput.terminator)) {
|
||||
break;
|
||||
//break; // Do nothing.
|
||||
} else {
|
||||
MIOOBRecord band = processMIOOBRecord(token, id);
|
||||
if (band != null) {
|
||||
|
@ -131,15 +131,14 @@ public class MIParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
MIOOBRecord[] bands =
|
||||
(MIOOBRecord[]) oobs.toArray(new MIOOBRecord[oobs.size()]);
|
||||
MIOOBRecord[] bands = (MIOOBRecord[]) oobs.toArray(new MIOOBRecord[oobs.size()]);
|
||||
mi.setMIOOBRecords(bands);
|
||||
mi.setMIResultRecord(rr);
|
||||
return mi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming '^' was deleted.
|
||||
* Assuming '^' was deleted from the Result Record.
|
||||
*/
|
||||
private MIResultRecord processMIResultRecord(StringBuffer buffer, int id) {
|
||||
MIResultRecord rr = new MIResultRecord();
|
||||
|
@ -174,6 +173,7 @@ public class MIParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Find OutOfBand Records depending on the starting token.
|
||||
*/
|
||||
private MIOOBRecord processMIOOBRecord(StringBuffer buffer, int id) {
|
||||
MIOOBRecord oob = null;
|
||||
|
@ -235,7 +235,8 @@ public class MIParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Assuming that the usual leading comma was consume.
|
||||
* Assuming that the usual leading comma was consumed.
|
||||
* Extract the MI Result comma seperated responses.
|
||||
*/
|
||||
private MIResult[] processMIResults(StringBuffer buffer) {
|
||||
List aList = new ArrayList();
|
||||
|
@ -255,7 +256,7 @@ public class MIParser {
|
|||
|
||||
/**
|
||||
* Construct the MIResult. Characters will be consume/delete
|
||||
* has moving forward constructing the AST.
|
||||
* moving forward constructing the AST.
|
||||
*/
|
||||
private MIResult processMIResult(StringBuffer buffer) {
|
||||
MIResult result = new MIResult();
|
||||
|
@ -353,6 +354,14 @@ public class MIParser {
|
|||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* MI C-String rather MICOnst values are enclose in double quotes
|
||||
* and any double quotes or backslash in the string are escaped.
|
||||
* Assuming the starting double quote was removed.
|
||||
* This method will stop at the closing double quote remove the extra
|
||||
* backslach escaping and return the string __without__ the enclosing double quotes
|
||||
* The orignal StringBuffer will move forward.
|
||||
*/
|
||||
private String translateCString(StringBuffer buffer) {
|
||||
boolean escape = false;
|
||||
boolean closingQuotes = false;
|
||||
|
|
|
@ -20,7 +20,7 @@ public class MIStackListArgumentsInfo extends MIInfo {
|
|||
super(out);
|
||||
}
|
||||
|
||||
public MIFrame[] getFrames() {
|
||||
public MIFrame[] getMIFrames() {
|
||||
if (frames == null) {
|
||||
parse();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public class MIStackListFramesInfo extends MIInfo {
|
|||
if (frames == null) {
|
||||
parse();
|
||||
}
|
||||
return null;
|
||||
return frames;
|
||||
}
|
||||
|
||||
void parse() {
|
||||
|
|
|
@ -14,19 +14,14 @@ public class MIThreadSelectInfo extends MIInfo {
|
|||
|
||||
public MIThreadSelectInfo(MIOutput out) {
|
||||
super(out);
|
||||
parse();
|
||||
}
|
||||
|
||||
public int getNewThreadId() {
|
||||
if (frame == null) {
|
||||
parse();
|
||||
}
|
||||
return threadId;
|
||||
}
|
||||
|
||||
public MIFrame getFrame() {
|
||||
if (frame == null) {
|
||||
parse();
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.List;
|
|||
*/
|
||||
public class MIVarListChildrenInfo extends MIInfo {
|
||||
|
||||
MIChild[] children = new MIChild[0];
|
||||
MIChild[] children;
|
||||
int numchild;
|
||||
|
||||
public MIVarListChildrenInfo(MIOutput record) {
|
||||
|
|
Loading…
Add table
Reference in a new issue