diff options
34 files changed, 1118 insertions, 979 deletions
diff --git a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/util/TCFDataCache.java b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/util/TCFDataCache.java index 186e68555..9b6394973 100644 --- a/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/util/TCFDataCache.java +++ b/plugins/org.eclipse.tm.tcf.core/src/org/eclipse/tm/tcf/util/TCFDataCache.java @@ -132,6 +132,24 @@ public abstract class TCFDataCache<V> implements Runnable { } /** + * If the cache is not valid, initiate data retrieval and + * add a client call-back to cache wait list. + * Client call-backs are activated when cache state changes. + * Call-backs are removed from waiting list after that. + * It is responsibility of clients to check if the state change was one they are waiting for. + * If the cache is valid do nothing and return true. + * @param cb - a call-back object + * @return true if the cache is already valid + */ + public boolean validate(Runnable cb) { + if (!validate()) { + wait(cb); + return false; + } + return true; + } + + /** * End cache pending state. * @param token - pending command handle. * @param error - data retrieval error or null diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/BreakpointCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/BreakpointCommand.java index ba9275fbf..22c83772d 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/BreakpointCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/BreakpointCommand.java @@ -20,9 +20,11 @@ import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpoint; -import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; -import org.eclipse.tm.tcf.protocol.Protocol; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; +import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame; import org.eclipse.tm.tcf.services.IBreakpoints; +import org.eclipse.tm.tcf.util.TCFDataCache; +import org.eclipse.tm.tcf.util.TCFTask; import org.eclipse.ui.IWorkbenchPart; @@ -30,47 +32,50 @@ public class BreakpointCommand implements IToggleBreakpointsTargetExtension { public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { if (selection.isEmpty()) return false; - Object obj = ((IStructuredSelection)selection).getFirstElement(); - if (obj instanceof TCFNode) { - final TCFNode node = (TCFNode)obj; - if (node == null) return false; - final boolean[] res = new boolean[1]; - Protocol.invokeAndWait(new Runnable() { - public void run() { - res[0] = node.getAddress() != null; + final Object obj = ((IStructuredSelection)selection).getFirstElement(); + return new TCFTask<Boolean>() { + public void run() { + TCFDataCache<BigInteger> addr_cache = null; + if (obj instanceof TCFNodeExecContext) addr_cache = ((TCFNodeExecContext)obj).getAddress(); + if (obj instanceof TCFNodeStackFrame) addr_cache = ((TCFNodeStackFrame)obj).getAddress(); + if (addr_cache != null) { + if (!addr_cache.validate(this)) return; + done(addr_cache.getData() != null); } - }); - return res[0]; - } - else { - return false; - } + else { + done(false); + } + } + }.getE(); } public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { if (selection.isEmpty()) return; - Object obj = ((IStructuredSelection)selection).getFirstElement(); - if (obj instanceof TCFNode) { - final TCFNode node = (TCFNode)obj; - if (node == null) return; - final CoreException[] res = new CoreException[1]; - Protocol.invokeAndWait(new Runnable() { - public void run() { - try { - BigInteger addr = node.getAddress(); - if (addr == null) return; - Map<String,Object> m = new HashMap<String,Object>(); - m.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); - m.put(IBreakpoints.PROP_LOCATION, addr.toString()); - new TCFBreakpoint(ResourcesPlugin.getWorkspace().getRoot(), m); - } - catch (CoreException x) { - res[0] = x; + final Object obj = ((IStructuredSelection)selection).getFirstElement(); + CoreException x = new TCFTask<CoreException>() { + public void run() { + try { + TCFDataCache<BigInteger> addr_cache = null; + if (obj instanceof TCFNodeExecContext) addr_cache = ((TCFNodeExecContext)obj).getAddress(); + if (obj instanceof TCFNodeStackFrame) addr_cache = ((TCFNodeStackFrame)obj).getAddress(); + if (addr_cache != null) { + if (!addr_cache.validate(this)) return; + BigInteger addr = addr_cache.getData(); + if (addr != null) { + Map<String,Object> m = new HashMap<String,Object>(); + m.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); + m.put(IBreakpoints.PROP_LOCATION, addr.toString()); + new TCFBreakpoint(ResourcesPlugin.getWorkspace().getRoot(), m); + } } + done(null); + } + catch (CoreException x) { + done(x); } - }); - if (res[0] != null) throw res[0]; - } + } + }.getE(); + if (x != null) throw x; } public boolean canToggleLineBreakpoints(IWorkbenchPart part, ISelection selection) { diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/ResumeCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/ResumeCommand.java index 236dfc30b..0b3899935 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/ResumeCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/ResumeCommand.java @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.commands.IDebugCommandRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; import org.eclipse.debug.core.commands.IResumeHandler; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; @@ -26,6 +27,7 @@ import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; import org.eclipse.tm.tcf.protocol.IToken; import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; public class ResumeCommand implements IResumeHandler { @@ -48,8 +50,9 @@ public class ResumeCommand implements IResumeHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null) { node = node.getParent(); @@ -59,8 +62,10 @@ public class ResumeCommand implements IResumeHandler { break; } else { - if (((TCFNodeExecContext)node).isSuspended() && - ctx.canResume(IRunControl.RM_RESUME)) res = true; + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended && ctx.canResume(IRunControl.RM_RESUME)) res = true; break; } } @@ -84,8 +89,9 @@ public class ResumeCommand implements IResumeHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null) { node = node.getParent(); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java index 66726f50a..4a6face7f 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SignalsDialog.java @@ -107,10 +107,7 @@ class SignalsDialog extends Dialog { return new TCFTask<Signal[]>(channel) { public void run() { - if (!signal_state.validate()) { - signal_state.wait(this); - return; - } + if (!signal_state.validate(this)) return; if (signal_state.getError() != null) error(signal_state.getError()); else done(signal_state.getData().list); } @@ -212,10 +209,7 @@ class SignalsDialog extends Dialog { @Override protected boolean startDataRetrieval() { - if (!signal_list.validate()) { - signal_list.wait(this); - return false; - } + if (!signal_list.validate(this)) return false; IProcesses prs = channel.getRemoteService(IProcesses.class); final SignalList sigs = signal_list.getData(); if (prs == null || sigs == null) { @@ -384,10 +378,7 @@ class SignalsDialog extends Dialog { try { final SignalState state = new TCFTask<SignalState>(channel) { public void run() { - if (!signal_state.validate()) { - signal_state.wait(this); - return; - } + if (!signal_state.validate(this)) return; if (signal_state.getError() != null) error(signal_state.getError()); else done(signal_state.getData()); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepCommand.java index 89a212bbd..cf0177022 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepCommand.java @@ -18,6 +18,7 @@ import org.eclipse.debug.core.commands.IDebugCommandHandler; import org.eclipse.debug.core.commands.IDebugCommandRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; import org.eclipse.jface.text.source.Annotation; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; @@ -25,6 +26,7 @@ import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; abstract class StepCommand implements IDebugCommandHandler { @@ -51,14 +53,18 @@ abstract class StepCommand implements IDebugCommandHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null || !canExecute(ctx)) { node = node.getParent(); } else { - if (((TCFNodeExecContext)node).isSuspended()) res = true; + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended) res = true; break; } } @@ -82,8 +88,9 @@ abstract class StepCommand implements IDebugCommandHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null || !canExecute(ctx)) { node = node.getParent(); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepIntoCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepIntoCommand.java index 36284c264..24144247a 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepIntoCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepIntoCommand.java @@ -51,21 +51,21 @@ public class StepIntoCommand extends StepCommand implements IStepIntoHandler { @Override protected TCFDataCache<TCFSourceRef> getLineInfo() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return null; return frame.getLineInfo(); } @Override protected TCFDataCache<StackTraceContext> getStackFrame() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return null; return frame.getStackTraceContext(); } @Override protected int getStackFrameIndex() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return 0; return frame.getFrameNo(); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepOverCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepOverCommand.java index 68fd7e475..81a0880cb 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepOverCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepOverCommand.java @@ -54,21 +54,21 @@ public class StepOverCommand extends StepCommand implements IStepOverHandler { @Override protected TCFDataCache<TCFSourceRef> getLineInfo() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return null; return frame.getLineInfo(); } @Override protected TCFDataCache<StackTraceContext> getStackFrame() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return null; return frame.getStackTraceContext(); } @Override protected int getStackFrameIndex() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return 0; return frame.getFrameNo(); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java index b4558639c..68719dbbc 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java @@ -51,14 +51,14 @@ public class StepReturnCommand extends StepCommand implements IStepReturnHandler @Override protected TCFDataCache<StackTraceContext> getStackFrame() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return null; return frame.getStackTraceContext(); } @Override protected int getStackFrameIndex() { - if (frame == null) frame = node.getTopFrame(); + if (frame == null) frame = node.getStackTrace().getTopFrame(); if (frame == null) return 0; return frame.getFrameNo(); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SuspendCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SuspendCommand.java index 441a6e59b..06a7554f8 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SuspendCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/SuspendCommand.java @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.commands.IDebugCommandRequest; import org.eclipse.debug.core.commands.IEnabledStateRequest; import org.eclipse.debug.core.commands.ISuspendHandler; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode; @@ -26,6 +27,7 @@ import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; import org.eclipse.tm.tcf.protocol.IToken; import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; public class SuspendCommand implements ISuspendHandler { @@ -48,8 +50,9 @@ public class SuspendCommand implements ISuspendHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null) { node = node.getParent(); @@ -59,8 +62,10 @@ public class SuspendCommand implements ISuspendHandler { break; } else { - if (((TCFNodeExecContext)node).isRunning() && - ctx.canSuspend()) res = true; + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && !state_data.is_suspended && ctx.canSuspend()) res = true; break; } } @@ -84,8 +89,9 @@ public class SuspendCommand implements ISuspendHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx == null) { node = node.getParent(); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/TerminateCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/TerminateCommand.java index 0783392db..2684ef519 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/TerminateCommand.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/TerminateCommand.java @@ -26,6 +26,7 @@ import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext; import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable; import org.eclipse.tm.tcf.protocol.IToken; import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.util.TCFDataCache; public class TerminateCommand implements ITerminateHandler { @@ -47,8 +48,9 @@ public class TerminateCommand implements ITerminateHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx != null && ctx.canTerminate()) { res = true; @@ -75,8 +77,9 @@ public class TerminateCommand implements ITerminateHandler { while (node != null && !node.isDisposed()) { IRunControl.RunControlContext ctx = null; if (node instanceof TCFNodeExecContext) { - if (!node.validateNode(this)) return; - ctx = ((TCFNodeExecContext)node).getRunContext().getData(); + TCFDataCache<IRunControl.RunControlContext> cache = ((TCFNodeExecContext)node).getRunContext(); + if (!cache.validate(this)) return; + ctx = cache.getData(); } if (ctx != null && ctx.canTerminate()) { set.add(ctx); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildren.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildren.java index c16f74869..6b249c266 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildren.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildren.java @@ -29,6 +29,10 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { private final Map<String,TCFNode> node_pool = new LinkedHashMap<String,TCFNode>(32, 0.75f, true); private boolean disposed; + private static final TCFNode[] EMPTY_NODE_ARRAY = new TCFNode[0]; + + private TCFNode[] array; + TCFChildren(IChannel channel) { super(channel); pool_margin = 0; @@ -61,6 +65,7 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { void dispose(String id) { node_pool.remove(id); if (isValid()) { + array = null; Map<String,TCFNode> data = getData(); if (data != null) data.remove(id); } @@ -99,6 +104,7 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { */ @Override public void set(IToken token, Throwable error, Map<String,TCFNode> data) { + array = null; if (disposed) { // A command can return data after the cache element has been disposed. // Just ignore the data in such case. @@ -121,6 +127,7 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { @Override public void reset(Map<String,TCFNode> data) { assert !disposed; + array = null; if (data != null) { super.reset(data); addToPool(data); @@ -131,6 +138,24 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { } /** + * Invalidate the cache. If retrieval is in progress - let it continue. + */ + @Override + public void reset() { + super.reset(); + array = null; + } + + /** + * Force cache to invalid state, cancel pending data retrieval if any. + */ + @Override + public void cancel() { + super.cancel(); + array = null; + } + + /** * Add a node to collection of children. * @param n - a node. */ @@ -139,6 +164,7 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { assert node_pool.get(n.id) == null; node_pool.put(n.id, n); if (isValid()) { + array = null; Map<String,TCFNode> data = getData(); if (data != null) data.put(n.id, n); } @@ -166,28 +192,16 @@ public abstract class TCFChildren extends TCFDataCache<Map<String,TCFNode>> { } /** - * Return index of given child node. - * @param n - a child node - * @return - node index or -1 if node is not found in children list - */ - int getIndexOf(TCFNode n) { - TCFNode[] arr = toArray(); - for (int i = 0; i < arr.length; i++) { - if (arr[i] == n) return i; - } - return -1; - } - - /** * Return current children nodes as an array. * @return array of nodes. */ TCFNode[] toArray() { assert isValid(); + if (array != null) return array; Map<String,TCFNode> data = getData(); - if (data == null) return new TCFNode[0]; - TCFNode[] arr = data.values().toArray(new TCFNode[data.size()]); - Arrays.sort(arr); - return arr; + if (data == null) return array = EMPTY_NODE_ARRAY; + array = data.values().toArray(new TCFNode[data.size()]); + Arrays.sort(array); + return array; } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenExpressions.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenExpressions.java index 59ac7ca1d..cbb2f1dab 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenExpressions.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenExpressions.java @@ -44,7 +44,6 @@ public class TCFChildrenExpressions extends TCFChildren { reset(); if (g != generation) return; node.addModelDelta(IModelDelta.CONTENT); - node.model.fireModelChanged(); } }); } @@ -87,7 +86,7 @@ public class TCFChildrenExpressions extends TCFChildren { for (final IExpression e : exp_manager.getExpressions()) { String text = e.getExpressionText(); TCFNodeExpression n = findScript(text); - if (n == null) add(n = new TCFNodeExpression(node, text, null, null, -1)); + if (n == null) add(n = new TCFNodeExpression(node, text, null, null, -1, null)); n.setSortPosition(cnt++); data.put(n.id, n); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenLocalVariables.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenLocalVariables.java index b51c18924..f18aa9da9 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenLocalVariables.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenLocalVariables.java @@ -46,7 +46,7 @@ public class TCFChildrenLocalVariables extends TCFChildren { data = new HashMap<String,TCFNode>(); for (String id : contexts) { TCFNodeExpression n = (TCFNodeExpression)node.model.getNode(id); - if (n == null) n = new TCFNodeExpression(node, null, null, id, -1); + if (n == null) n = new TCFNodeExpression(node, null, null, id, -1, null); assert n.id.equals(id); assert n.parent == node; n.setSortPosition(cnt++); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenStackTrace.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenStackTrace.java index 418e55241..d5bf9ec64 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenStackTrace.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenStackTrace.java @@ -47,7 +47,7 @@ public class TCFChildrenStackTrace extends TCFChildren { reset(null); } - TCFNodeStackFrame getTopFrame() { + public TCFNodeStackFrame getTopFrame() { assert isValid(); return (TCFNodeStackFrame)node.model.getNode(top_frame_id); } @@ -64,10 +64,7 @@ public class TCFChildrenStackTrace extends TCFChildren { protected boolean startDataRetrieval() { final HashMap<String,TCFNode> data = new HashMap<String,TCFNode>(); TCFDataCache<TCFContextState> state = node.getState(); - if (!state.validate()) { - state.wait(this); - return false; - } + if (!state.validate(this)) return false; Throwable state_error = state.getError(); TCFContextState state_data = state.getData(); if (state_error != null || state_data == null || !state_data.is_suspended) { diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenSubExpressions.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenSubExpressions.java index 8f194580e..5eed50104 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenSubExpressions.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFChildrenSubExpressions.java @@ -13,7 +13,6 @@ package org.eclipse.tm.internal.tcf.debug.ui.model; import java.util.HashMap; import java.util.Map; -import org.eclipse.tm.tcf.protocol.IToken; import org.eclipse.tm.tcf.services.IExpressions; import org.eclipse.tm.tcf.services.ISymbols; import org.eclipse.tm.tcf.util.TCFDataCache; @@ -74,49 +73,61 @@ public class TCFChildrenSubExpressions extends TCFChildren { if (exp instanceof TCFNodeExpression) break; exp = exp.parent; } - final TCFDataCache<ISymbols.Symbol> type = ((TCFNodeExpression)exp).getType(); - if (!type.validate()) { - type.wait(this); - return false; - } + final TCFDataCache<IExpressions.Value> value_cache = ((TCFNodeExpression)exp).getValue(); + if (!value_cache.validate(this)) return false; + final IExpressions.Value value_data = value_cache.getData(); final ISymbols syms = node.model.getLaunch().getService(ISymbols.class); - final ISymbols.Symbol type_sym = type.getData(); - if (syms == null || type_sym == null) { + if (value_data == null || syms == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + final TCFDataCache<ISymbols.Symbol> type_cache = node.model.getSymbolInfoCache( + value_data.getExeContextID(), value_data.getTypeID()); + if (type_cache == null) { set(null, null, new HashMap<String,TCFNode>()); return true; } - ISymbols.TypeClass type_class = type_sym.getTypeClass(); + if (!type_cache.validate(this)) return false; + final ISymbols.Symbol type_data = type_cache.getData(); + if (type_data == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + ISymbols.TypeClass type_class = type_data.getTypeClass(); if (par_level > 0 && type_class != ISymbols.TypeClass.array) { set(null, null, new HashMap<String,TCFNode>()); return true; } if (type_class == ISymbols.TypeClass.composite) { - command = syms.getChildren(type_sym.getID(), new ISymbols.DoneGetChildren() { - public void doneGetChildren(IToken token, Exception error, String[] contexts) { - Map<String,TCFNode> data = null; - if (command == token && error == null) { - int cnt = 0; - data = new HashMap<String,TCFNode>(); - for (String id : contexts) { - TCFNodeExpression n = findField(id); - if (n == null) n = new TCFNodeExpression(node, null, id, null, -1); - n.setSortPosition(cnt++); - data.put(n.id, n); - } - } - set(token, error, data); + TCFDataCache<String[]> children_cache = node.model.getSymbolChildrenCache(type_data.getExeContextID(), type_data.getID()); + if (children_cache == null) { + set(null, null, new HashMap<String,TCFNode>()); + return true; + } + if (!children_cache.validate(this)) return false; + String[] children_data = children_cache.getData(); + Map<String,TCFNode> data = null; + if (children_data != null) { + int cnt = 0; + data = new HashMap<String,TCFNode>(); + for (String id : children_data) { + TCFNodeExpression n = findField(id); + if (n == null) n = new TCFNodeExpression(node, null, id, null, -1, type_data); + n.setSortPosition(cnt++); + data.put(n.id, n); } - }); - return false; + } + set(null, children_cache.getError(), data); + return true; } if (type_class == ISymbols.TypeClass.array) { Map<String,TCFNode> data = new HashMap<String,TCFNode>(); int offs = par_level > 0 ? par_offs : 0; - int size = par_level > 0 ? par_size : type_sym.getLength(); + int size = par_level > 0 ? par_size : type_data.getLength(); if (size <= 100) { for (int i = offs; i < offs + size; i++) { TCFNodeExpression n = findIndex(i); - if (n == null) n = new TCFNodeExpression(node, null, null, null, i); + if (n == null) n = new TCFNodeExpression(node, null, null, null, i, type_data); n.setSortPosition(i); data.put(n.id, n); } @@ -138,24 +149,40 @@ public class TCFChildrenSubExpressions extends TCFChildren { if (type_class == ISymbols.TypeClass.pointer) { Map<String,TCFNode> data = new HashMap<String,TCFNode>(); TCFDataCache<IExpressions.Value> value = ((TCFNodeExpression)exp).getValue(); - if (!value.validate()) { - value.wait(this); - return false; - } + if (!value.validate(this)) return false; IExpressions.Value v = value.getData(); if (v != null && !isNull(v.getValue())) { - TCFDataCache<ISymbols.Symbol> base_type = node.model.getSymbolInfoCache( - type_sym.getExeContextID(), type_sym.getBaseTypeID()); - if (!base_type.validate()) { - base_type.wait(this); - return false; - } - ISymbols.Symbol base_type_sym = base_type.getData(); - if (base_type_sym == null || base_type_sym.getSize() != 0) { - TCFNodeExpression n = findIndex(0); - if (n == null) n = new TCFNodeExpression(node, null, null, null, 0); - n.setSortPosition(0); - data.put(n.id, n); + TCFDataCache<ISymbols.Symbol> base_type_cache = node.model.getSymbolInfoCache( + type_data.getExeContextID(), type_data.getBaseTypeID()); + if (base_type_cache != null) { + if (!base_type_cache.validate(this)) return false; + ISymbols.Symbol base_type_data = base_type_cache.getData(); + if (base_type_data == null || base_type_data.getSize() != 0) { + if (base_type_data.getTypeClass() == ISymbols.TypeClass.composite) { + TCFDataCache<String[]> children_cache = node.model.getSymbolChildrenCache( + base_type_data.getExeContextID(), base_type_data.getID()); + if (children_cache != null) { + if (!children_cache.validate(this)) return false; + String[] children_data = children_cache.getData(); + if (children_data != null) { + int cnt = 0; + data = new HashMap<String,TCFNode>(); + for (String id : children_data) { + TCFNodeExpression n = findField(id); + if (n == null) n = new TCFNodeExpression(node, null, id, null, -1, type_data); + n.setSortPosition(cnt++); + data.put(n.id, n); + } + } + } + } + else { + TCFNodeExpression n = findIndex(0); + if (n == null) n = new TCFNodeExpression(node, null, null, null, 0, type_data); + n.setSortPosition(0); + data.put(n.id, n); + } + } } } set(null, null, data); diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFDetailPane.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFDetailPane.java index b6892e5fe..fad8df09b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFDetailPane.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFDetailPane.java @@ -83,7 +83,6 @@ public class TCFDetailPane implements IDetailPane { } private String getDetailText(ArrayList<TCFNode> nodes, Runnable done) { - if (!TCFNode.validateNodes(nodes, done)) return null; StringBuffer bf = new StringBuffer(); for (TCFNode n : nodes) { if (n instanceof TCFNodeExpression) { diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFMemoryBlockRetrieval.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFMemoryBlockRetrieval.java index 980d2fd08..538139f1b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFMemoryBlockRetrieval.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFMemoryBlockRetrieval.java @@ -86,10 +86,7 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension { expression_value = new TCFDataCache<IExpressions.Value>(channel) { @Override protected boolean startDataRetrieval() { - if (!remote_expression.validate()) { - remote_expression.wait(this); - return false; - } + if (!remote_expression.validate(this)) return false; final IExpressions.Expression ctx = remote_expression.getData(); if (ctx == null) { set(null, null, null); @@ -107,23 +104,21 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension { expression_type = new TCFDataCache<ISymbols.Symbol>(channel) { @Override protected boolean startDataRetrieval() { - if (!expression_value.validate()) { - expression_value.wait(this); - return false; + if (!expression_value.validate(this)) return false; + IExpressions.Value val = expression_value.getData(); + if (val == null) { + set(null, expression_value.getError(), null); + return true; } - String id = null; - if (expression_value.getData() != null) id = expression_value.getData().getTypeID(); - ISymbols syms = launch.getService(ISymbols.class); - if (id == null || syms == null) { + TCFDataCache<ISymbols.Symbol> type_cache = exec_ctx.getModel().getSymbolInfoCache( + val.getExeContextID(), val.getTypeID()); + if (type_cache == null) { set(null, null, null); return true; } - command = syms.getContext(id, new ISymbols.DoneGetContext() { - public void doneGetContext(IToken token, Exception error, ISymbols.Symbol sym) { - set(token, error, sym); - } - }); - return false; + if (!type_cache.validate(this)) return false; + set(null, type_cache.getError(), type_cache.getData()); + return true; } }; } @@ -170,8 +165,10 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension { if (exec_ctx.isDisposed()) { error("Context is disposed"); } - else if (exec_ctx.validateNode(this)) { - IMemory.MemoryContext mem = exec_ctx.getMemoryContext().getData(); + else { + TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext(); + if (!cache.validate(this)) return; + IMemory.MemoryContext mem = cache.getData(); if (mem == null) { error("Context does not provide memory access"); } @@ -248,8 +245,10 @@ class TCFMemoryBlockRetrieval implements IMemoryBlockRetrievalExtension { if (exec_ctx.isDisposed()) { error("Context is disposed"); } - else if (exec_ctx.validateNode(this)) { - final IMemory.MemoryContext mem = exec_ctx.getMemoryContext().getData(); + else { + TCFDataCache<IMemory.MemoryContext> cache = exec_ctx.getMemoryContext(); + if (!cache.validate(this)) return; + final IMemory.MemoryContext mem = cache.getData(); if (mem == null) { error("Context does not provide memory access"); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java index d23699e6e..e4d856680 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModel.java @@ -18,7 +18,6 @@ import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.commands.IDisconnectHandler; @@ -74,6 +73,7 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.graphics.Device; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; import org.eclipse.tm.internal.tcf.debug.ui.Activator; @@ -223,7 +223,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } } } - fireModelChanged(); } public void contextChanged(IMemory.MemoryContext[] contexts) { @@ -237,7 +236,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, for (TCFDataCache<ISymbols.Symbol> s : m.values()) s.cancel(); } } - fireModelChanged(); } public void contextRemoved(final String[] context_ids) { @@ -249,7 +247,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onMemoryChanged(addr, size); } - fireModelChanged(); } }; @@ -262,7 +259,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, ((TCFNodeExecContext)node).onContainerResumed(); } } - fireModelChanged(); } public void containerSuspended(String context, String pc, String reason, @@ -277,7 +273,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextSuspended(pc, reason, params); } - fireModelChanged(); runSuspendTrigger(node); } @@ -294,7 +289,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } } } - fireModelChanged(); } public void contextChanged(IRunControl.RunControlContext[] contexts) { @@ -304,7 +298,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, ((TCFNodeExecContext)node).onContextChanged(contexts[i]); } } - fireModelChanged(); } public void contextException(String context, String msg) { @@ -312,7 +305,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextException(msg); } - fireModelChanged(); } public void contextRemoved(final String[] context_ids) { @@ -324,7 +316,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeExecContext) { ((TCFNodeExecContext)node).onContextResumed(); } - fireModelChanged(); display.asyncExec(new Runnable() { public void run() { Activator.getAnnotationManager().onContextResumed(TCFModel.this, context); @@ -339,7 +330,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, exe.onContextSuspended(pc, reason, params); setDebugViewSelection(context, false); } - fireModelChanged(); runSuspendTrigger(node); } }; @@ -352,7 +342,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, ((TCFNodeExecContext)node).onRegistersChanged(); } } - fireModelChanged(); } public void registerChanged(String context) { @@ -360,7 +349,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node instanceof TCFNodeRegister) { ((TCFNodeRegister)node).onValueChanged(); } - fireModelChanged(); } }; @@ -398,8 +386,9 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, while (n != null && !n.isDisposed()) { if (n instanceof TCFNodeExecContext) { TCFNodeExecContext e = (TCFNodeExecContext)n; - if (!e.validateNode(this)) return; - if (e.getMemoryContext() != null) { + TCFDataCache<IMemory.MemoryContext> cache = e.getMemoryContext(); + if (!cache.validate(this)) return; + if (cache.getData() != null) { o = mem_retrieval.get(e.id); if (o == null) { TCFMemoryBlockRetrieval m = new TCFMemoryBlockRetrieval(e); @@ -502,24 +491,15 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } void onContextActionsDone() { - fireModelChanged(); } void onProxyInstalled(final IPresentationContext p, final TCFModelProxy mp) { - Protocol.invokeLater(new Runnable() { - public void run() { - model_proxies.put(p, mp); - } - }); + model_proxies.put(p, mp); } void onProxyDisposed(final IPresentationContext p) { - Protocol.invokeAndWait(new Runnable() { - public void run() { - assert model_proxies.containsKey(p); - model_proxies.remove(p); - } - }); + assert model_proxies.containsKey(p); + model_proxies.remove(p); } private void onContextRemoved(final String[] context_ids) { @@ -532,7 +512,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (node.parent == launch_node) close_channel = true; } } - fireModelChanged(); if (close_channel) { // Close debug session if the last context is removed: onLastContextRemoved(); @@ -551,8 +530,9 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, public void run() { if (launch_node == null) return; if (launch_node.isDisposed()) return; - if (!launch_node.validateNode(this)) return; - if (launch_node.getContextCount() != 0) return; + TCFChildrenExecContext children = launch_node.getChildren(); + if (!children.validate(this)) return; + if (children.size() != 0) return; launch.onLastContextRemoved(); } }); @@ -565,7 +545,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, void launchChanged() { if (launch_node != null) { launch_node.addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); - fireModelChanged(); } else { refreshLaunchView(); @@ -599,12 +578,6 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, mem_retrieval.remove(id); } - void fireModelChanged() { - assert Protocol.isDispatchThread(); - if (launch.hasPendingContextActions()) return; - for (TCFModelProxy p : model_proxies.values()) p.fireModelChanged(); - } - public Display getDisplay() { return display; } @@ -625,6 +598,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } public TCFDataCache<ISymbols.Symbol> getSymbolInfoCache(String mem_id, final String sym_id) { + if (mem_id == null || sym_id == null) return null; Map<String,TCFDataCache<ISymbols.Symbol>> m = symbols.get(mem_id); if (m == null) symbols.put(mem_id, m = new HashMap<String,TCFDataCache<ISymbols.Symbol>>()); TCFDataCache<ISymbols.Symbol> s = m.get(sym_id); @@ -648,6 +622,7 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, } public TCFDataCache<String[]> getSymbolChildrenCache(String mem_id, final String sym_id) { + if (mem_id == null || sym_id == null) return null; Map<String,TCFDataCache<String[]>> m = symbol_children.get(mem_id); if (m == null) symbol_children.put(mem_id, m = new HashMap<String,TCFDataCache<String[]>>()); TCFDataCache<String[]> s = m.get(sym_id); @@ -767,23 +742,20 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, TCFNode node = getNode(node_id); if (node == null) return; if (node.disposed) return; - if (!node.validateNode(this)) return; if (cnt != debug_view_selection_cnt) return; if (node instanceof TCFNodeExecContext) { - if (!((TCFNodeExecContext)node).isSuspended()) return; - TCFNode frame = ((TCFNodeExecContext)node).getTopFrame(); - if (frame != null && !frame.disposed) { - if (!frame.validateNode(this)) return; - node = frame; - } + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)node).getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data == null || !state_data.is_suspended) return; + TCFChildrenStackTrace stack_trace = ((TCFNodeExecContext)node).getStackTrace(); + if (!stack_trace.validate(this)) return; + TCFNode frame = stack_trace.getTopFrame(); + if (frame != null && !frame.disposed) node = frame; } for (TCFModelProxy proxy : model_proxies.values()) { if (proxy.getPresentationContext().getId().equals(IDebugUIConstants.ID_DEBUG_VIEW)) { - proxy.fireModelChanged(); - proxy.addDelta(node, IModelDelta.REVEAL); - proxy.fireModelChanged(); - proxy.addDelta(node, IModelDelta.SELECT); - proxy.fireModelChanged(); + proxy.setSelection(node); } } } @@ -817,23 +789,24 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, if (element instanceof TCFNodeExecContext) { TCFNodeExecContext node = (TCFNodeExecContext)element; if (!node.disposed) { - if (!node.validateNode(this)) return; - if (node.isSuspended()) stack_frame = node.getTopFrame(); + TCFDataCache<TCFContextState> state_cache = node.getState(); + if (!state_cache.validate(this)) return; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended) { + TCFChildrenStackTrace stack_trace = ((TCFNodeExecContext)node).getStackTrace(); + if (!stack_trace.validate(this)) return; + stack_frame = stack_trace.getTopFrame(); + } } } else if (element instanceof TCFNodeStackFrame) { TCFNodeStackFrame node = (TCFNodeStackFrame)element; - if (!node.disposed) { - stack_frame = (TCFNodeStackFrame)element; - } + if (!node.disposed) stack_frame = (TCFNodeStackFrame)element; } } if (stack_frame != null) { TCFDataCache<TCFSourceRef> line_info = stack_frame.getLineInfo(); - if (!line_info.validate()) { - line_info.wait(this); - return; - } + if (!line_info.validate(this)) return; String editor_id = null; IEditorInput editor_input = null; Throwable error = line_info.getError(); @@ -903,7 +876,13 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider, }); } + /* + * Refresh Launch View. + * Normally the view is updated by sending deltas through model proxy. + * This method is used only when launch is not yet connected or already disconnected. + */ private void refreshLaunchView() { + // TODO: there should be a better way to refresh Launch View final Throwable error = launch.getError(); if (error != null) launch.setError(null); synchronized (Device.class) { diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelProxy.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelProxy.java index 95e09937a..879d96994 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelProxy.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelProxy.java @@ -13,50 +13,168 @@ package org.eclipse.tm.internal.tcf.debug.ui.model; import java.util.HashMap; import java.util.Map; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; +import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.Viewer; import org.eclipse.tm.tcf.protocol.Protocol; -public class TCFModelProxy extends AbstractModelProxy implements IModelProxy { +/** + * A model proxy represents a model for a specific presentation context and + * fires deltas to notify listeners of changes in the model. + */ +public class TCFModelProxy extends AbstractModelProxy implements IModelProxy, Runnable { private static final int CONTENT_FLAGS = IModelDelta.ADDED | IModelDelta.REMOVED | IModelDelta.REPLACED | IModelDelta.INSERTED | IModelDelta.CONTENT | IModelDelta.STATE; + private static final TCFNode[] EMPTY_NODE_ARRAY = new TCFNode[0]; + private final TCFModel model; - private final Map<TCFNode,Integer> deltas = new HashMap<TCFNode,Integer>(); + private final Map<TCFNode,Integer> node2flags = new HashMap<TCFNode,Integer>(); + private final Map<TCFNode,TCFNode[]> node2children = new HashMap<TCFNode,TCFNode[]>(); + private final Map<TCFNode,ModelDelta> node2delta = new HashMap<TCFNode,ModelDelta>(); + + private TCFNode selection; + private boolean posted; + private boolean disposed; + + private class ViewerUpdate implements IViewerUpdate { + + IStatus status; + + public Object getElement() { + return null; + } + + public TreePath getElementPath() { + return null; + } + + public IPresentationContext getPresentationContext() { + return TCFModelProxy.this.getPresentationContext(); + } + + public Object getViewerInput() { + return TCFModelProxy.this.getProxyViewer().getInput(); + } + + public void cancel() { + } + + public void done() { + } + + public IStatus getStatus() { + return status; + } + + public boolean isCanceled() { + return false; + } + + public void setStatus(IStatus status) { + this.status = status; + } + } + + private class ChildrenCountUpdate extends ViewerUpdate implements IChildrenCountUpdate { + + int count; + + public void setChildCount(int count) { + this.count = count; + + } + } + + private class ChildrenUpdate extends ViewerUpdate implements IChildrenUpdate { + + int length; + TCFNode[] children; + + void setLength(int length) { + this.length = length; + this.children = new TCFNode[length]; + } + + public int getLength() { + return length; + } + + public int getOffset() { + return 0; + } + + public void setChild(Object child, int offset) { + children[offset] = (TCFNode)child; + } + } + + private final ChildrenCountUpdate children_count_update = new ChildrenCountUpdate(); + private final ChildrenUpdate children_update = new ChildrenUpdate(); + + private TCFNode pending_node; TCFModelProxy(TCFModel model) { this.model = model; } - public synchronized void installed(Viewer viewer) { + public void installed(Viewer viewer) { super.installed(viewer); - IPresentationContext p = getPresentationContext(); - if (p != null) model.onProxyInstalled(p, this); + Protocol.invokeAndWait(new Runnable() { + public void run() { + assert !disposed; + IPresentationContext p = getPresentationContext(); + if (p != null) model.onProxyInstalled(p, TCFModelProxy.this); + } + }); } - public synchronized void dispose() { - IPresentationContext p = getPresentationContext(); - if (p != null) model.onProxyDisposed(p); + public void dispose() { + Protocol.invokeAndWait(new Runnable() { + public void run() { + assert !disposed; + IPresentationContext p = getPresentationContext(); + if (p != null) model.onProxyDisposed(p); + disposed = true; + } + }); super.dispose(); } void addDelta(TCFNode node, int flags) { if (flags != 0) { - Integer delta = deltas.get(node); + Integer delta = node2flags.get(node); if (delta != null) { - deltas.put(node, Integer.valueOf(delta.intValue() | flags)); + node2flags.put(node, delta.intValue() | flags); } else { - deltas.put(node, Integer.valueOf(flags)); + node2flags.put(node, flags); } + post(); + } + } + + void setSelection(TCFNode node) { + selection = node; + addDelta(node, IModelDelta.REVEAL); + } + + void post() { + if (!posted) { + Protocol.invokeLater(this); + posted = true; } } @@ -64,41 +182,92 @@ public class TCFModelProxy extends AbstractModelProxy implements IModelProxy { return getViewer(); } - private ModelDelta makeDelta(ModelDelta root, Map<TCFNode,ModelDelta> map, TCFNode node, int flags) { - boolean content_only = (flags & ~CONTENT_FLAGS) == 0; - ModelDelta delta = map.get(node); + private TCFNode[] getNodeChildren(TCFNode node) { + TCFNode[] res = node2children.get(node); + if (res == null) { + if (node.disposed) { + res = EMPTY_NODE_ARRAY; + } + else if (!node.getData(children_count_update, null)) { + pending_node = node; + res = EMPTY_NODE_ARRAY; + } + else { + children_update.setLength(children_count_update.count); + if (!node.getData(children_update, null)) { + assert false; + pending_node = node; + res = EMPTY_NODE_ARRAY; + } + else { + res = children_update.children; + } + } + node2children.put(node, res); + } + return res; + } + + private int getNodeIndex(TCFNode node) { + TCFNode[] arr = getNodeChildren(node.parent); + for (int i = 0; i < arr.length; i++) { + if (arr[i] == node) return i; + } + return -1; + } + + private ModelDelta makeDelta(ModelDelta root, TCFNode node, int flags) { + ModelDelta delta = node2delta.get(node); if (delta == null) { - IPresentationContext p = getPresentationContext(); if (node.parent == null) { - if (content_only && (root.getFlags() & IModelDelta.CONTENT) != 0) return null; - delta = root.addNode(model.getLaunch(), -1, flags, node.getChildrenCount(p)); + delta = root.addNode(model.getLaunch(), -1, flags, getNodeChildren(node).length); } else { - ModelDelta parent = makeDelta(root, map, node.parent, 0); + int parent_flags = 0; + Integer parent_flags_obj = node2flags.get(node.parent); + if (parent_flags_obj != null) parent_flags = parent_flags_obj; + if ((flags & ~CONTENT_FLAGS) == 0 && (parent_flags & IModelDelta.CONTENT) != 0) return null; + ModelDelta parent = makeDelta(root, node.parent, parent_flags); if (parent == null) return null; - if (content_only && (parent.getFlags() & IModelDelta.CONTENT) != 0) return null; - delta = parent.addNode( - node, node.parent.getNodeIndex(p, node), - flags, node.getChildrenCount(p)); + delta = parent.addNode(node, getNodeIndex(node), flags, getNodeChildren(node).length); } - map.put(node, delta); - } - else if (flags != 0) { - delta.setFlags(delta.getFlags() | flags); + node2delta.put(node, delta); } + assert delta.getFlags() == flags; return delta; } - void fireModelChanged() { + public void run() { + posted = false; assert Protocol.isDispatchThread(); - if (deltas.isEmpty()) return; + if (disposed) return; + if (node2flags.isEmpty()) return; + pending_node = null; + node2children.clear(); + node2delta.clear(); ModelDelta root = new ModelDelta(DebugPlugin.getDefault().getLaunchManager(), IModelDelta.NO_CHANGE); - Map<TCFNode,ModelDelta> map = new HashMap<TCFNode,ModelDelta>(); - for (TCFNode node : deltas.keySet()) { - makeDelta(root, map, node, deltas.get(node).intValue()); + for (TCFNode node : node2flags.keySet()) makeDelta(root, node, node2flags.get(node)); + if (pending_node == null) { + node2flags.clear(); + if (!node2delta.isEmpty()) { + fireModelChanged(root); + node2delta.clear(); + } + if (selection != null) { + root = new ModelDelta(DebugPlugin.getDefault().getLaunchManager(), IModelDelta.NO_CHANGE); + makeDelta(root, selection, IModelDelta.SELECT); + fireModelChanged(root); + node2delta.clear(); + selection = null; + } + } + else if (pending_node.getData(children_count_update, this)) { + assert false; + post(); + } + else { + posted = true; } - deltas.clear(); - if (map.isEmpty()) return; - fireModelChanged(root); + node2children.clear(); } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelSelectionPolicy.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelSelectionPolicy.java index fce5e1472..b196b56db 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelSelectionPolicy.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFModelSelectionPolicy.java @@ -15,6 +15,8 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; +import org.eclipse.tm.tcf.util.TCFDataCache; import org.eclipse.tm.tcf.util.TCFTask; class TCFModelSelectionPolicy implements IModelSelectionPolicy { @@ -52,8 +54,10 @@ class TCFModelSelectionPolicy implements IModelSelectionPolicy { TCFNode n = node; while (n != null && !n.isDisposed()) { if (n instanceof TCFNodeExecContext) { - if (!n.validateNode(this)) return; - if (((TCFNodeExecContext)n).isSuspended()) { + TCFDataCache<TCFContextState> cache = ((TCFNodeExecContext)n).getState(); + if (!cache.validate(this)) return; + TCFContextState state = cache.getData(); + if (state != null && state.is_suspended) { done(true); return; } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java index 8f08a8d50..0b668342a 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNode.java @@ -10,9 +10,6 @@ *******************************************************************************/ package org.eclipse.tm.internal.tcf.debug.ui.model; -import java.math.BigInteger; -import java.util.Collection; - import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.Status; @@ -22,7 +19,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; -import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; import org.eclipse.tm.tcf.protocol.IChannel; import org.eclipse.tm.tcf.protocol.Protocol; @@ -140,33 +136,6 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo } /** - * Get index of a node in this node children list - * @param p - presentation context - * @return node index or -1 if unknown - */ - public int getNodeIndex(IPresentationContext p, TCFNode n) { - return -1; - } - - /** - * Get children count of the node. - * @param p - presentation context - * @return children count or -1 if unknown - */ - public int getChildrenCount(IPresentationContext p) { - return -1; - } - - /** - * Return address of this node. - * For executable contexts and stack frames address is current PC. - * @return BigInteger - remote memory address that is associated with this node - */ - public BigInteger getAddress() { - return null; - } - - /** * Retrieve children count for a presentation context. * @param result - children count update request. */ @@ -176,8 +145,7 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo if (!result.isCanceled()) { IChannel channel = model.getLaunch().getChannel(); if (!disposed && channel.getState() == IChannel.STATE_OPEN) { - if (!validateNode(this)) return; - getData(result); + if (!getData(result, this)) return; } else { result.setChildCount(0); @@ -199,8 +167,7 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo if (!result.isCanceled()) { IChannel channel = model.getLaunch().getChannel(); if (!disposed && channel.getState() == IChannel.STATE_OPEN) { - if (!validateNode(this)) return; - getData(result); + if (!getData(result, this)) return; } result.setStatus(Status.OK_STATUS); } @@ -219,8 +186,7 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo if (!result.isCanceled()) { IChannel channel = model.getLaunch().getChannel(); if (!disposed && channel.getState() == IChannel.STATE_OPEN) { - if (!validateNode(this)) return; - getData(result); + if (!getData(result, this)) return; } else { result.setHasChilren(false); @@ -242,8 +208,7 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo if (!result.isCanceled()) { IChannel channel = model.getLaunch().getChannel(); if (!disposed && channel.getState() == IChannel.STATE_OPEN) { - if (!validateNode(this)) return; - getData(result); + if (!getData(result, this)) return; } else { result.setLabel("...", 0); @@ -257,46 +222,53 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo /** * Retrieve children count for a presentation context. - * The node is validated before calling this method, - * so the method should return cached data. * The method is always called on TCF dispatch thread. * @param result - children count update request. + * @param done - client call back interface, during data waiting it is + * called every time new portion of data becomes available. + * @return false if waiting data retrieval, true if all done. */ - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { result.setChildCount(0); + return true; } /** * Retrieve children for a presentation context. - * The node is validated before calling this method, - * so the method should return cached data. * The method is always called on TCF dispatch thread. * @param result - children update request. + * @param done - client call back interface, during data waiting it is + * called every time new portion of data becomes available. + * @return false if waiting data retrieval, true if all done. */ - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { + return true; } /** * Check if the node has children in a presentation context. - * The node is validated before calling this method, - * so the method should return cached data. * The method is always called on TCF dispatch thread. * @param result - "has children" update request. + * @param done - client call back interface, during data waiting it is + * called every time new portion of data becomes available. + * @return false if waiting data retrieval, true if all done. */ - protected void getData(IHasChildrenUpdate result) { + protected boolean getData(IHasChildrenUpdate result, Runnable done) { result.setHasChilren(false); + return true; } /** * Retrieve node label for a presentation context. - * The node is validated before calling this method, - * so the method should return cached data. * The method is always called on TCF dispatch thread. * @param result - label update request. + * @param done - client call back interface, during data waiting it is + * called every time new portion of data becomes available. + * @return false if waiting data retrieval, true if all done. */ - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); + protected boolean getData(ILabelUpdate result, Runnable done) { result.setLabel(id, 0); + return true; } /** @@ -321,49 +293,8 @@ public abstract class TCFNode extends PlatformObject implements Comparable<TCFNo } /*--------------------------------------------------------------------------------------*/ - /* Node data retrieval state machine */ - - /** - * Validate node - retrieve and put into a cache missing data from remote peer. - * The method should initiate retrieval of all data needed by TCFNode.update() methods. - * Validation is done asynchronously. If the node is already valid, - * the method should return true. Otherwise, it returns false, - * adds 'done' into 'wait_list', and later call-backs from 'wait_list' are invoked. - * Note: activation of call-back does not mean all data is retrieved, - * it only means that node state changed, client should call validateNode() again, - * until the method returns true. - * @param done - call-back object to call when node state changes. - * @return true if the node is already valid, false if validation is started. - */ - public abstract boolean validateNode(Runnable done); - - /** - * Clients can use this method to validate a collection of nodes. - * Validation of multiple nodes is expensive and should be avoided - * when possible. - * - * Validation is performed in background, and 'done' call-back is - * activated when nodes state changes. - * - * @param nodes - * @return true if all nodes are already valid, false if validation is started. - */ - public static boolean validateNodes(Collection<TCFNode> nodes, Runnable done) { - TCFNode pending = null; - for (TCFNode n : nodes) { - if (!n.validateNode(null)) pending = n; - } - if (pending != null && !pending.validateNode(done)) return false; - return true; - } - - /*--------------------------------------------------------------------------------------*/ /* Misc */ - protected String getImageName() { - return null; - } - public int compareTo(TCFNode n) { return id.compareTo(n.id); } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeArrayPartition.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeArrayPartition.java index 6bd85d15f..adaf843ce 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeArrayPartition.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeArrayPartition.java @@ -17,7 +17,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; -import org.eclipse.tm.tcf.util.TCFDataCache; public class TCFNodeArrayPartition extends TCFNode { @@ -53,12 +52,15 @@ public class TCFNodeArrayPartition extends TCFNode { } @Override - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { + if (!children.validate(done)) return false; result.setChildCount(children.size()); + return true; } @Override - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { + if (!children.validate(done)) return false; TCFNode[] arr = children.toArray(); int offset = 0; int r_offset = result.getOffset(); @@ -69,16 +71,18 @@ public class TCFNodeArrayPartition extends TCFNode { } offset++; } + return true; } @Override - protected void getData(IHasChildrenUpdate result) { - result.setHasChilren(children.size() > 0); + protected boolean getData(IHasChildrenUpdate result, Runnable done) { + result.setHasChilren(true); + return true; } @Override - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); + protected boolean getData(ILabelUpdate result, Runnable done) { + result.setImageDescriptor(ImageCache.getImageDescriptor(ImageCache.IMG_ARRAY_PARTITION), 0); String[] cols = result.getColumnIds(); String name = "[" + offs + ".." + (offs + size - 1) + "]"; if (cols == null || cols.length <= 1) { @@ -95,6 +99,7 @@ public class TCFNodeArrayPartition extends TCFNode { } } } + return true; } @Override @@ -107,20 +112,6 @@ public class TCFNodeArrayPartition extends TCFNode { } @Override - public boolean validateNode(Runnable done) { - TCFDataCache<?> pending = null; - if (!children.validate()) pending = children; - if (pending == null) return true; - pending.wait(done); - return false; - } - - @Override - protected String getImageName() { - return ImageCache.IMG_ARRAY_PARTITION; - } - - @Override public int compareTo(TCFNode n) { TCFNodeArrayPartition p = (TCFNodeArrayPartition)n; if (offs < p.offs) return -1; diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExecContext.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExecContext.java index 1c08fd9e4..3fea23382 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExecContext.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExecContext.java @@ -11,6 +11,7 @@ package org.eclipse.tm.internal.tcf.debug.ui.model; import java.math.BigInteger; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; @@ -19,7 +20,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.swt.graphics.RGB; import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; @@ -46,6 +46,7 @@ public class TCFNodeExecContext extends TCFNode { private final TCFDataCache<IRunControl.RunControlContext> run_context; private final TCFDataCache<IProcesses.ProcessContext> prs_context; private final TCFDataCache<TCFContextState> state; + private final TCFDataCache<BigInteger> address; private final Map<BigInteger,TCFSourceRef> line_info_cache; @@ -120,10 +121,7 @@ public class TCFNodeExecContext extends TCFNode { @Override protected boolean startDataRetrieval() { assert command == null; - if (!run_context.validate()) { - run_context.wait(this); - return false; - } + if (!run_context.validate(this)) return false; IRunControl.RunControlContext ctx = run_context.getData(); if (ctx == null || !ctx.hasState()) { set(null, null, null); @@ -142,6 +140,29 @@ public class TCFNodeExecContext extends TCFNode { return false; } }; + address = new TCFDataCache<BigInteger>(channel) { + @Override + protected boolean startDataRetrieval() { + if (!run_context.validate(this)) return false; + IRunControl.RunControlContext ctx = run_context.getData(); + if (ctx == null || !ctx.hasState()) { + set(null, run_context.getError(), null); + return true; + } + if (!state.validate(this)) return false; + TCFContextState s = state.getData(); + if (s == null) { + set(null, state.getError(), null); + return true; + } + if (s.suspend_pc == null) { + set(null, null, null); + return true; + } + set(null, null, new BigInteger(s.suspend_pc)); + return true; + } + }; } @Override @@ -150,6 +171,7 @@ public class TCFNodeExecContext extends TCFNode { prs_context.reset(null); mem_context.reset(null); state.reset(null); + address.reset(null); children_exec.dispose(); children_stack.dispose(); super.dispose(); @@ -189,43 +211,8 @@ public class TCFNodeExecContext extends TCFNode { return mem_context; } - public boolean isRunning() { - assert Protocol.isDispatchThread(); - if (!run_context.isValid()) return false; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx == null || !ctx.hasState()) return false; - if (!state.isValid()) return false; - TCFContextState s = state.getData(); - return s != null && !s.is_suspended; - } - - public boolean isSuspended() { - assert Protocol.isDispatchThread(); - if (!run_context.isValid()) return false; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx == null || !ctx.hasState()) return false; - if (!state.isValid()) return false; - TCFContextState s = state.getData(); - return s != null && s.is_suspended; - } - - @Override - public BigInteger getAddress() { - assert Protocol.isDispatchThread(); - if (!run_context.isValid()) return null; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx == null || !ctx.hasState()) return null; - if (!state.isValid()) return null; - TCFContextState s = state.getData(); - if (s == null) return null; - if (s.suspend_pc == null) return null; - return new BigInteger(s.suspend_pc); - } - - public TCFNodeStackFrame getTopFrame() { - assert Protocol.isDispatchThread(); - if (!children_stack.isValid()) return null; - return children_stack.getTopFrame(); + public TCFDataCache<BigInteger> getAddress() { + return address; } public TCFDataCache<TCFContextState> getState() { @@ -241,77 +228,45 @@ public class TCFNodeExecContext extends TCFNode { } @Override - public int getNodeIndex(IPresentationContext p, TCFNode n) { - if (!run_context.isValid()) return -1; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx != null && ctx.hasState()) { - if (!children_stack.isValid()) return -1; - if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getId())) { - TCFNodeStackFrame frame = children_stack.getTopFrame(); - if (frame == null) return -1; - return frame.getNodeIndex(p, n); - } - return children_stack.getIndexOf(n); - } - if (!children_exec.isValid()) return -1; - return children_exec.getIndexOf(n); - } - - @Override - public int getChildrenCount(IPresentationContext p) { - if (!run_context.isValid()) return -1; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx != null && ctx.hasState()) { - if (!children_stack.isValid()) return -1; - if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(p.getId())) { - TCFNodeStackFrame frame = children_stack.getTopFrame(); - if (frame == null) return -1; - return frame.getChildrenCount(p); - } - return children_stack.size(); - } - if (!children_exec.isValid()) return -1; - return children_exec.size(); - } - - @Override - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { + if (!run_context.validate(done)) return false; IRunControl.RunControlContext ctx = run_context.getData(); if (ctx != null && ctx.hasState()) { + if (!children_stack.validate(done)) return false; if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) { TCFNodeStackFrame frame = children_stack.getTopFrame(); - if (frame == null) result.setChildCount(0); - else frame.getData(result); + if (frame != null) return frame.getData(result, done); + result.setChildCount(0); } else { result.setChildCount(children_stack.size()); } } else { + if (!children_exec.validate(done)) return false; result.setChildCount(children_exec.size()); } + return true; } @Override - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { TCFNode[] arr = null; + if (!run_context.validate(done)) return false; IRunControl.RunControlContext ctx = run_context.getData(); if (ctx != null && ctx.hasState()) { + if (!children_stack.validate(done)) return false; if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) { TCFNodeStackFrame frame = children_stack.getTopFrame(); - if (frame == null) { - arr = new TCFNode[0]; - } - else { - frame.getData(result); - return; - } + if (frame != null) return frame.getData(result, done); + arr = new TCFNode[0]; } else { arr = children_stack.toArray(); } } else { + if (!children_exec.validate(done)) return false; arr = children_exec.toArray(); } int offset = 0; @@ -323,29 +278,36 @@ public class TCFNodeExecContext extends TCFNode { } offset++; } + return true; } @Override - protected void getData(IHasChildrenUpdate result) { + protected boolean getData(IHasChildrenUpdate result, Runnable done) { + if (!run_context.validate(done)) return false; IRunControl.RunControlContext ctx = run_context.getData(); if (ctx != null && ctx.hasState()) { + if (!children_stack.validate(done)) return false; if (!IDebugUIConstants.ID_DEBUG_VIEW.equals(result.getPresentationContext().getId())) { TCFNodeStackFrame frame = children_stack.getTopFrame(); if (frame == null) result.setHasChilren(false); - else frame.getData(result); + else if (!frame.getData(result, done)) return false; } else { result.setHasChilren(children_stack.size() > 0); } } else { + if (!children_exec.validate(done)) return false; result.setHasChilren(children_exec.size() > 0); } + return true; } + @SuppressWarnings("unchecked") @Override - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); + protected boolean getData(ILabelUpdate result, Runnable done) { + if (!run_context.validate(done)) return false; + String image_name = null; String label = id; Throwable error = run_context.getError(); if (error != null) { @@ -355,11 +317,35 @@ public class TCFNodeExecContext extends TCFNode { else { IRunControl.RunControlContext ctx = run_context.getData(); if (ctx != null) { - if (isRunning()) { + if (!state.validate(done)) return false; + TCFContextState state_data = state.getData(); + if (ctx.hasState()) { + // Thread + if (state_data != null && state_data.is_terminated) image_name = ImageCache.IMG_THREAD_TERMINATED; + else if (state_data != null && state_data.is_suspended) image_name = ImageCache.IMG_THREAD_SUSPENDED; + else image_name = ImageCache.IMG_THREAD_RUNNNIG; + } + else { + // Thread container (process) + Boolean b = hasSuspendedChildren(done); + if (b == null) return false; + if (b.booleanValue()) image_name = ImageCache.IMG_PROCESS_SUSPENDED; + else image_name = ImageCache.IMG_PROCESS_RUNNING; + } + if (state_data != null && !state_data.is_suspended) { label += " (Running)"; } - else if (isSuspended()) { - String r = state.getData().suspend_reason; + else if (state_data != null && state_data.is_suspended) { + String r = state_data.suspend_reason; + if (state_data.suspend_params != null) { + Collection<String> ids = (Collection<String>)state_data.suspend_params.get(IRunControl.STATE_BREAKPOINT_IDS); + if (ids != null) { + for (String id : ids) { + String s = model.getLaunch().getContextActionBreakpoint(id); + if (s != null) r = s; + } + } + } if (r != null) { label += " (" + r + ")"; } @@ -371,7 +357,9 @@ public class TCFNodeExecContext extends TCFNode { if (file != null) label += " " + file; } } + result.setImageDescriptor(ImageCache.getImageDescriptor(image_name), 0); result.setLabel(label, 0); + return true; } void onContextAdded(IRunControl.RunControlContext context) { @@ -410,6 +398,7 @@ public class TCFNodeExecContext extends TCFNode { if (!ctx.hasState()) return; } state.reset(); + address.reset(); children_stack.onSuspended(); addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); } @@ -434,6 +423,7 @@ public class TCFNodeExecContext extends TCFNode { s.suspend_params = params; state.reset(s); children_stack.onSuspended(); + address.reset(); resumed_cnt++; addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); } @@ -448,12 +438,10 @@ public class TCFNodeExecContext extends TCFNode { if (cnt != resumed_cnt) return; if (disposed) return; children_stack.onResumed(); - if (!validateNode(this)) return; addModelDelta(IModelDelta.CONTENT); if (parent instanceof TCFNodeExecContext) { ((TCFNodeExecContext)parent).onChildResumedOrSuspended(); } - model.fireModelChanged(); } }); } @@ -476,96 +464,34 @@ public class TCFNodeExecContext extends TCFNode { addModelDelta(IModelDelta.CONTENT); } - @Override - public boolean validateNode(Runnable done) { - assert !disposed; - TCFDataCache<?> pending = null; - - if (!mem_context.validate()) pending = mem_context; - if (!run_context.validate()) pending = run_context; - if (!prs_context.validate()) pending = prs_context; - if (pending != null) { - pending.wait(done); - return false; - } - - if (!state.validate()) pending = state; - if (!children_exec.validate()) pending = children_exec; - if (!children_stack.validate()) pending = children_stack; - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx != null && !ctx.hasState()) { - // Container need to validate children for - // hasSuspendedChildren() method to return valid value. - TCFDataCache<?> dt = validateChildrenState(); - if (dt != null) pending = dt; - } - if (pending != null) { - pending.wait(done); - return false; - } - - TCFNodeStackFrame frame = children_stack.getTopFrame(); - if (frame != null && !frame.validateNode(done)) return false; - - return true; - } - - // Validate children state for hasSuspendedChildren() - // Return TCFDataCache to wait for if validation is pending. - private TCFDataCache<?> validateChildrenState() { - if (!children_exec.validate()) return children_exec; - TCFDataCache<?> pending = null; - for (TCFNode n : children_exec.getData().values()) { - if (!(n instanceof TCFNodeExecContext)) continue; - TCFNodeExecContext e = (TCFNodeExecContext)n; - if (!e.run_context.validate()) { - pending = e.run_context; - continue; - } - IRunControl.RunControlContext ctx = e.run_context.getData(); - if (ctx == null) continue; - if (ctx.hasState() && !e.state.validate()) pending = e.state; - if (ctx.isContainer()) pending = e.validateChildrenState(); - } - return pending; - } - // Return true if at least one child is suspended // The method will fail if node is not validated, see validateChildrenState() - private boolean hasSuspendedChildren() { + private Boolean hasSuspendedChildren(Runnable done) { + if (!children_exec.validate(done)) return null; Map<String,TCFNode> m = children_exec.getData(); if (m == null) return false; for (TCFNode n : m.values()) { if (!(n instanceof TCFNodeExecContext)) continue; TCFNodeExecContext e = (TCFNodeExecContext)n; + if (!e.run_context.validate(done)) return null; IRunControl.RunControlContext ctx = e.run_context.getData(); if (ctx == null) continue; - if (ctx.hasState() && e.isSuspended()) return true; - if (ctx.isContainer() && e.hasSuspendedChildren()) return true; + if (ctx.hasState()) { + TCFDataCache<TCFContextState> state_cache = e.getState(); + if (!state_cache.validate(done)) return null; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended) return true; + } + if (ctx.isContainer()) { + Boolean b = e.hasSuspendedChildren(done); + if (b == null) return null; + if (b.booleanValue()) return true; + } } return false; } @Override - protected String getImageName() { - IRunControl.RunControlContext ctx = run_context.getData(); - if (ctx != null && ctx.hasState()) { - // Thread - TCFContextState s = state.getData(); - if (s != null && s.is_terminated) return ImageCache.IMG_THREAD_TERMINATED; - if (s != null && s.is_suspended) return ImageCache.IMG_THREAD_SUSPENDED; - return ImageCache.IMG_THREAD_RUNNNIG; - } - else if (ctx != null) { - // Thread container (process) - //if (terminated) return ImageCache.IMG_PROCESS_TERMINATED; - if (hasSuspendedChildren()) return ImageCache.IMG_PROCESS_SUSPENDED; - return ImageCache.IMG_PROCESS_RUNNING; - } - return super.getImageName(); - } - - @Override public int compareTo(TCFNode n) { if (n instanceof TCFNodeExecContext) { TCFNodeExecContext f = (TCFNodeExecContext)n; diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExpression.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExpression.java index e0be1e6be..3893ede6e 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExpression.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeExpression.java @@ -31,16 +31,23 @@ import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.tm.internal.tcf.debug.ui.Activator; import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; +import org.eclipse.tm.tcf.core.Command; import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IErrorReport; import org.eclipse.tm.tcf.protocol.IToken; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IExpressions; +import org.eclipse.tm.tcf.services.IMemory; import org.eclipse.tm.tcf.services.ISymbols; +import org.eclipse.tm.tcf.services.IMemory.MemoryError; import org.eclipse.tm.tcf.util.TCFDataCache; import org.eclipse.tm.tcf.util.TCFTask; public class TCFNodeExpression extends TCFNode implements IElementEditor { + // TODO: User commands: Display As Array, Cast To Type, Restore Original Type, Add Global Variables, Remove Global Variables + // TODO: enable Change Value user command + private final String script; private final String field_id; private final String var_id; @@ -51,34 +58,22 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { private final TCFDataCache<IExpressions.Value> value; private final TCFDataCache<ISymbols.Symbol> type; private final TCFChildrenSubExpressions children; + private final TCFDataCache<String> type_name; + private final TCFDataCache<String> string; private int sort_pos; private static int expr_cnt; - TCFNodeExpression(final TCFNode parent, final String script, final String field_id, final String var_id, final int index) { + TCFNodeExpression(final TCFNode parent, final String script, + String field_id, final String var_id, final int index, final ISymbols.Symbol parent_type) { super(parent, var_id != null ? var_id : "Expr" + expr_cnt++); assert script != null || field_id != null || var_id != null || index >= 0; this.script = script; this.field_id = field_id; this.var_id = var_id; + this.field = field_id == null ? null : model.getSymbolInfoCache(parent_type.getExeContextID(), field_id); this.index = index; IChannel channel = model.getLaunch().getChannel(); - field = new TCFDataCache<ISymbols.Symbol>(channel) { - @Override - protected boolean startDataRetrieval() { - ISymbols syms = model.getLaunch().getService(ISymbols.class); - if (field_id == null || syms == null) { - set(null, null, null); - return true; - } - command = syms.getContext(field_id, new ISymbols.DoneGetContext() { - public void doneGetContext(IToken token, Exception error, ISymbols.Symbol sym) { - set(token, error, sym); - } - }); - return false; - } - }; text = new TCFDataCache<String>(channel) { @Override protected boolean startDataRetrieval() { @@ -87,10 +82,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { return true; } if (var_id != null) { - if (!expression.validate()) { - expression.wait(this); - return false; - } + if (!expression.validate(this)) return false; if (expression.getData() == null) { set(null, expression.getError(), null); return true; @@ -106,20 +98,14 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { TCFNode n = parent; while (n instanceof TCFNodeArrayPartition) n = n.parent; TCFDataCache<String> t = ((TCFNodeExpression)n).getExpressionText(); - if (!t.validate()) { - t.wait(this); - return false; - } + if (!t.validate(this)) return false; String e = t.getData(); if (e == null) { set(null, t.getError(), null); return true; } - if (field_id != null) { - if (!field.validate()) { - field.wait(this); - return false; - } + if (field != null) { + if (!field.validate(this)) return false; if (field.getData() == null) { set(null, field.getError(), null); return true; @@ -129,7 +115,12 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { set(null, new Exception("Field nas no name"), null); return true; } - e = "(" + e + ")." + name; + if (parent_type.getTypeClass() == ISymbols.TypeClass.pointer) { + e = "(" + e + ")->" + name; + } + else { + e = "(" + e + ")." + name; + } } else if (index == 0) { e = "*(" + e + ")"; @@ -157,10 +148,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { }); } else { - if (!text.validate()) { - text.wait(this); - return false; - } + if (!text.validate(this)) return false; String e = text.getData(); if (e == null) { set(null, text.getError(), null); @@ -193,10 +181,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { value = new TCFDataCache<IExpressions.Value>(channel) { @Override protected boolean startDataRetrieval() { - if (!expression.validate()) { - expression.wait(this); - return false; - } + if (!expression.validate(this)) return false; final IExpressions.Expression ctx = expression.getData(); if (ctx == null) { set(null, null, null); @@ -214,29 +199,254 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { type = new TCFDataCache<ISymbols.Symbol>(channel) { @Override protected boolean startDataRetrieval() { - if (!value.validate()) { - value.wait(this); - return false; - } - IExpressions.Value v = value.getData(); - if (v == null) { - set(null, null, null); + if (!value.validate(this)) return false; + IExpressions.Value val = value.getData(); + if (val == null) { + set(null, value.getError(), null); return true; } - String ctx_id = v.getExeContextID(); - String type_id = v.getTypeID(); - if (ctx_id == null || type_id == null) { + TCFDataCache<ISymbols.Symbol> type_cache = model.getSymbolInfoCache( + val.getExeContextID(), val.getTypeID()); + if (type_cache == null) { set(null, null, null); return true; } - TCFDataCache<ISymbols.Symbol> s = model.getSymbolInfoCache(ctx_id, type_id); - if (!s.validate()) { - s.wait(this); + if (!type_cache.validate(this)) return false; + set(null, type_cache.getError(), type_cache.getData()); + return true; + } + }; + string = new TCFDataCache<String>(channel) { + IMemory.MemoryContext mem; + ISymbols.Symbol base_type_data; + boolean big_endian; + BigInteger addr; + byte[] buf; + int size; + int offs; + @Override + protected boolean startDataRetrieval() { + if (addr != null && size == 0) { + // data is ASCII string + if (buf == null) buf = new byte[256]; + if (offs >= buf.length) { + byte[] tmp = new byte[buf.length * 2]; + System.arraycopy(buf, 0, tmp, 0, buf.length); + buf = tmp; + } + command = mem.get(addr.add(BigInteger.valueOf(offs)), 1, buf, offs, 1, 0, new IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (error != null) { + String msg = "Cannot read string value: "; + if (error instanceof IErrorReport) { + msg += Command.toErrorString(((IErrorReport)error).getAttributes()); + } + else { + msg += error.getLocalizedMessage(); + } + set(command, null, msg); + } + else if (buf[offs] == 0 || offs >= 2048) { + StringBuffer bf = new StringBuffer(); + bf.append('"'); + for (int i = 0; i < offs; i++) { + int ch = buf[i] & 0xff; + if (ch >= ' ' && ch < 0x7f) { + bf.append((char)ch); + } + else { + switch (ch) { + case '\r': bf.append("\\r"); break; + case '\n': bf.append("\\n"); break; + case '\b': bf.append("\\b"); break; + case '\t': bf.append("\\t"); break; + case '\f': bf.append("\\f"); break; + default: + bf.append('\\'); + bf.append((char)('0' + ch / 64)); + bf.append((char)('0' + ch / 8 % 8)); + bf.append((char)('0' + ch % 8)); + } + } + } + if (buf[offs] == 0) bf.append('"'); + else bf.append("..."); + set(command, null, bf.toString()); + } + else if (command == token) { + command = null; + offs++; + run(); + } + } + }); return false; } - set(null, s.getError(), s.getData()); + if (addr != null) { + // data is a struct + if (offs != size) { + if (buf == null || buf.length < size) buf = new byte[size]; + command = mem.get(addr, 1, buf, 0, size, 0, new IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (error != null) { + set(command, error, null); + } + else if (command == token) { + command = null; + offs = size; + run(); + } + } + }); + return false; + } + StringBuffer bf = new StringBuffer(); + if (!appendCompositeValueText(bf, 1, base_type_data, buf, 0, size, big_endian, this)) return false; + set(null, null, bf.toString()); + return true; + } + TCFNode n = parent; + while (n != null) { + if (n instanceof TCFNodeExecContext) { + TCFDataCache<IMemory.MemoryContext> mem_cache = ((TCFNodeExecContext)n).getMemoryContext(); + if (!mem_cache.validate(this)) return false; + mem = mem_cache.getData(); + if (mem != null) break; + } + n = n.parent; + } + if (mem != null) { + if (!type.validate(this)) return false; + ISymbols.Symbol type_data = type.getData(); + if (type_data != null) { + switch (type_data.getTypeClass()) { + case pointer: + TCFDataCache<ISymbols.Symbol> base_type_cahce = model.getSymbolInfoCache( + type_data.getExeContextID(), type_data.getBaseTypeID()); + if (base_type_cahce != null) { + if (!base_type_cahce.validate(this)) return false; + base_type_data = base_type_cahce.getData(); + if (base_type_data != null) { + switch (base_type_data.getTypeClass()) { + case integer: + case cardinal: + if (base_type_data.getSize() != 1) break; + case composite: + if (base_type_data.getSize() == 0) break; + if (!value.validate(this)) return false; + IExpressions.Value v = value.getData(); + if (v != null) { + byte[] data = v.getValue(); + big_endian = v.isBigEndian(); + BigInteger a = toBigInteger(data, 0, data.length, big_endian, false); + if (!a.equals(BigInteger.valueOf(0))) { + addr = a; + offs = 0; + size = 0; + if (base_type_data.getTypeClass() == ISymbols.TypeClass.composite) { + size = base_type_data.getSize(); + } + Protocol.invokeLater(this); + return false; + } + } + } + } + } + } + } + } + set(null, null, null); + return true; + } + @Override + public void reset() { + super.reset(); + addr = null; + } + }; + type_name = new TCFDataCache<String>(channel) { + String name; + TCFDataCache<ISymbols.Symbol> type_cache; + @Override + protected boolean startDataRetrieval() { + if (name == null) type_cache = type; + if (!type_cache.validate(this)) return false; + String s = null; + boolean get_base_type = false; + ISymbols.Symbol t = type_cache.getData(); + if (t != null) { + s = t.getName(); + if (s != null && t.getTypeClass() == ISymbols.TypeClass.composite) { + s = "struct " + s; + } + if (s == null && t.getSize() == 0) s = "void"; + if (s == null) { + switch (t.getTypeClass()) { + case integer: + switch (t.getSize()) { + case 1: s = "char"; break; + case 2: s = "short"; break; + case 4: s = "int"; break; + case 8: s = "long long"; break; + default: s = "<Integer>"; break; + } + break; + case cardinal: + switch (t.getSize()) { + case 1: s = "unsigned char"; break; + case 2: s = "unsigned short"; break; + case 4: s = "unsigned"; break; + case 8: s = "unsigned long long"; break; + default: s = "<Unsigned>"; break; + } + break; + case real: + switch (t.getSize()) { + case 4: s = "float"; break; + case 8: s = "double"; break; + default: s = "<Float>"; break; + } + break; + case pointer: + s = "*"; + get_base_type = true; + break; + case array: + s = "[]"; + get_base_type = true; + break; + case composite: + s = "<Structure>"; + break; + case function: + s = "<Function>"; + break; + } + } + } + if (s == null) name = "N/A"; + else if (name == null) name = s; + else if (!get_base_type) name = s + " " + name; + else name = s + name; + if (get_base_type) { + type_cache = model.getSymbolInfoCache(t.getExeContextID(), t.getBaseTypeID()); + if (type_cache == null) { + name = "N/A"; + } + else { + Protocol.invokeLater(this); + return false; + } + } + set(null, null, name); return true; } + @Override + public void reset() { + super.reset(); + name = null; + } }; children = new TCFChildrenSubExpressions(this, 0, 0, 0); } @@ -245,6 +455,8 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { void dispose() { value.reset(null); type.reset(null); + type_name.reset(null); + string.reset(null); children.reset(null); children.dispose(); super.dispose(); @@ -270,6 +482,8 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { void onSuspended() { value.reset(); type.reset(); + type_name.reset(); + string.reset(); children.reset(); children.onSuspended(); addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); @@ -299,10 +513,6 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { return value; } - TCFDataCache<ISymbols.Symbol> getType() { - return type; - } - private BigInteger toBigInteger(byte[] data, int offs, int size, boolean big_endian, boolean sign_extension) { assert offs + size <= data.length; byte[] temp = null; @@ -389,52 +599,29 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } private void setTypeLabel(ILabelUpdate result, int col) { - String s = null; - ISymbols.Symbol t = type.getData(); - if (t != null) { - s = t.getName(); - if (s == null && t.getSize() == 0) s = "<Void>"; - if (s == null) { - switch (t.getTypeClass()) { - case integer: - s = "<Integer>"; - break; - case cardinal: - s = "<Unsigned>"; - break; - case real: - s = "<Float>"; - break; - case pointer: - s = "<Pointer>"; - break; - case array: - s = "<Array>"; - break; - case composite: - s = "<Structure>"; - break; - case function: - s = "<Function>"; - break; - } - } - } - if (s == null) s = "N/A"; - result.setLabel(s, col); + result.setLabel(type_name.getData(), col); } @Override - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); + protected boolean getData(ILabelUpdate result, Runnable done) { + TCFDataCache<?> pending = null; + if (field != null && !field.validate()) pending = field; + if (!expression.validate()) pending = expression; + if (!value.validate()) pending = value; + if (!type.validate()) pending = type; + if (!type_name.validate()) pending = type_name; + if (!children.validate()) pending = children; + if (pending != null) { + pending.wait(done); + return false; + } String name = null; if (script != null) name = script; if (name == null && index >= 0) name = "[" + index + "]"; - if (name == null && field_id != null && field.getData() != null) name = field.getData().getName(); + if (name == null && field != null && field.getData() != null) name = field.getData().getName(); if (name == null && var_id != null && expression.getData() != null) name = expression.getData().getExpression(); Throwable error = expression.getError(); if (error == null) error = value.getError(); - if (error == null) error = type.getError(); String[] cols = result.getColumnIds(); if (error != null) { if (cols == null || cols.length <= 1) { @@ -447,7 +634,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { if (c.equals(TCFColumnPresentationExpression.COL_NAME)) { result.setLabel(name, i); } - else if (c.equals(TCFColumnPresentationExpression.COL_TYPE) && type.getError() == null) { + else if (c.equals(TCFColumnPresentationExpression.COL_TYPE)) { setTypeLabel(result, i); } else { @@ -479,6 +666,8 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } } } + result.setImageDescriptor(ImageCache.getImageDescriptor(ImageCache.IMG_VARIABLE), 0); + return true; } private void appendErrorText(StringBuffer bf, Throwable error) { @@ -496,16 +685,10 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } } - private boolean appendArrayValueText(StringBuffer bf, int level, ISymbols.Symbol t, + private boolean appendArrayValueText(StringBuffer bf, int level, ISymbols.Symbol type, byte[] data, int offs, int size, boolean big_endian, Runnable done) { assert offs + size <= data.length; - TCFDataCache<ISymbols.Symbol> c = model.getSymbolInfoCache(t.getExeContextID(), t.getBaseTypeID()); - if (!c.validate()) { - c.wait(done); - return false; - } - ISymbols.Symbol b = c.getData(); - int length = t.getLength(); + int length = type.getLength(); if (level == 0) { if (size == length) { try { @@ -530,7 +713,6 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { bf.append('\n'); } } - if (b == null) return true; bf.append('['); if (length > 0) { int elem_size = size / length; @@ -540,7 +722,8 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { break; } if (n > 0) bf.append(", "); - if (!appendValueText(bf, level + 1, b, data, offs + n * elem_size, elem_size, big_endian, done)) return false; + if (!appendValueText(bf, level + 1, type.getExeContextID(), type.getBaseTypeID(), + data, offs + n * elem_size, elem_size, big_endian, done)) return false; } } bf.append(']'); @@ -548,87 +731,112 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { return true; } - private boolean appendCompositeValueText(StringBuffer bf, int level, ISymbols.Symbol t, + private boolean appendCompositeValueText(StringBuffer bf, int level, ISymbols.Symbol type, byte[] data, int offs, int size, boolean big_endian, Runnable done) { - TCFDataCache<String[]> c = model.getSymbolChildrenCache(t.getExeContextID(), t.getID()); - if (!c.validate()) { - c.wait(done); - return false; + TCFDataCache<String[]> children_cache = model.getSymbolChildrenCache(type.getExeContextID(), type.getID()); + if (children_cache == null) { + bf.append("{...}"); + return true; + } + if (!children_cache.validate(done)) return false; + String[] children_data = children_cache.getData(); + if (children_data == null) { + bf.append("{...}"); + return true; } - String[] ids = c.getData(); - if (ids == null) return true; bf.append('{'); - for (String id : ids) { - if (id != ids[0]) bf.append(", "); - TCFDataCache<ISymbols.Symbol> s = model.getSymbolInfoCache(t.getExeContextID(), id); - if (!s.validate()) { - s.wait(done); - return false; - } - ISymbols.Symbol f = s.getData(); - if (f == null || offs + f.getOffset() + f.getSize() > data.length) { + for (String id : children_data) { + if (id != children_data[0]) bf.append(", "); + TCFDataCache<ISymbols.Symbol> field_cache = model.getSymbolInfoCache(type.getExeContextID(), id); + if (!field_cache.validate(done)) return false; + ISymbols.Symbol field_data = field_cache.getData(); + if (field_data == null || offs + field_data.getOffset() + field_data.getSize() > data.length) { bf.append('?'); continue; } - bf.append(f.getName()); + bf.append(field_data.getName()); bf.append('='); - if (!appendValueText(bf, level + 1, f, data, offs + f.getOffset(), f.getSize(), big_endian, done)) return false; + if (!appendValueText(bf, level + 1, field_data.getExeContextID(), field_data.getTypeID(), + data, offs + field_data.getOffset(), field_data.getSize(), big_endian, done)) return false; } bf.append('}'); return true; } - private boolean appendValueText(StringBuffer bf, int level, ISymbols.Symbol t, + private boolean appendValueText(StringBuffer bf, int level, String ctx_id, String type_id, byte[] data, int offs, int size, boolean big_endian, Runnable done) { if (data == null) return true; - switch (t.getTypeClass()) { + TCFDataCache<ISymbols.Symbol> type_cahce = model.getSymbolInfoCache(ctx_id, type_id); + if (!type_cahce.validate(done)) return false; + ISymbols.Symbol type_data = type_cahce.getData(); + if (type_data == null) { + if (level == 0) { + bf.append("Hex: "); + bf.append(toNumberString(16, type_data, data, 0, data.length, big_endian)); + bf.append("\n"); + bf.append("Value type is not available\n"); + } + else { + bf.append(toNumberString(16, type_data, data, 0, data.length, big_endian)); + } + return true; + } + if (level == 0) { + if (!string.validate(done)) return false; + String s = string.getData(); + if (s != null) { + bf.append(s); + bf.append("\n"); + } + } + switch (type_data.getTypeClass()) { case enumeration: case integer: case cardinal: case real: if (level == 0) { bf.append("Size: "); - bf.append(t.getSize()); - bf.append(t.getSize() == 1 ? " byte\n" : " bytes\n"); - if (t.getSize() == 0) break; + bf.append(type_data.getSize()); + bf.append(type_data.getSize() == 1 ? " byte\n" : " bytes\n"); + if (type_data.getSize() == 0) break; bf.append("Dec: "); - bf.append(toNumberString(10, t, data, offs, size, big_endian)); + bf.append(toNumberString(10, type_data, data, offs, size, big_endian)); bf.append("\n"); bf.append("Oct: "); - bf.append(toNumberString(8, t, data, offs, size, big_endian)); + bf.append(toNumberString(8, type_data, data, offs, size, big_endian)); bf.append("\n"); bf.append("Hex: "); - bf.append(toNumberString(16, t, data, offs, size, big_endian)); + bf.append(toNumberString(16, type_data, data, offs, size, big_endian)); bf.append("\n"); } - else if (t.getTypeClass() == ISymbols.TypeClass.cardinal) { + else if (type_data.getTypeClass() == ISymbols.TypeClass.cardinal) { bf.append("0x"); - bf.append(toNumberString(16, t, data, offs, size, big_endian)); + bf.append(toNumberString(16, type_data, data, offs, size, big_endian)); } else { - bf.append(toNumberString(10, t, data, offs, size, big_endian)); + bf.append(toNumberString(10, type_data, data, offs, size, big_endian)); } break; case pointer: case function: if (level == 0) { bf.append("Oct: "); - bf.append(toNumberString(8, t, data, offs, size, big_endian)); + bf.append(toNumberString(8, type_data, data, offs, size, big_endian)); bf.append("\n"); bf.append("Hex: "); - bf.append(toNumberString(16, t, data, offs, size, big_endian)); + bf.append(toNumberString(16, type_data, data, offs, size, big_endian)); bf.append("\n"); } else { bf.append("0x"); - bf.append(toNumberString(16, t, data, offs, size, big_endian)); + bf.append(toNumberString(16, type_data, data, offs, size, big_endian)); } break; case array: - if (!appendArrayValueText(bf, level, t, data, offs, size, big_endian, done)) return false; + if (!appendArrayValueText(bf, level, type_data, data, offs, size, big_endian, done)) return false; break; case composite: - if (!appendCompositeValueText(bf, level, t, data, offs, size, big_endian, done)) return false; + if (!appendCompositeValueText(bf, level, type_data, data, offs, size, big_endian, done)) return false; break; default: bf.append('?'); @@ -638,37 +846,33 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } String getDetailText(Runnable done) { + if (!expression.validate(done)) return null; + if (!value.validate(done)) return null; StringBuffer bf = new StringBuffer(); appendErrorText(bf, expression.getError()); appendErrorText(bf, value.getError()); - appendErrorText(bf, type.getError()); if (bf.length() == 0) { IExpressions.Value v = value.getData(); if (v != null) { byte[] data = v.getValue(); boolean big_endian = v.isBigEndian(); - ISymbols.Symbol t = type.getData(); - if (t != null) { - if (!appendValueText(bf, 0, t, data, 0, data.length, big_endian, done)) return null; - } - else { - bf.append("Hex: "); - bf.append(toNumberString(16, t, data, 0, data.length, big_endian)); - bf.append("\n"); - bf.append("Value type is not available\n"); - } + if (!appendValueText(bf, 0, v.getExeContextID(), v.getTypeID(), + data, 0, data.length, big_endian, done)) return null; } } return bf.toString(); } @Override - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { + if (!children.validate(done)) return false; result.setChildCount(children.size()); + return true; } @Override - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { + if (!children.validate(done)) return false; TCFNode[] arr = children.toArray(); int offset = 0; int r_offset = result.getOffset(); @@ -679,11 +883,14 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } offset++; } + return true; } @Override - protected void getData(IHasChildrenUpdate result) { + protected boolean getData(IHasChildrenUpdate result, Runnable done) { + if (!children.validate(done)) return false; result.setHasChilren(children.size() > 0); + return true; } @Override @@ -696,24 +903,6 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { } @Override - public boolean validateNode(Runnable done) { - TCFDataCache<?> pending = null; - if (!field.validate()) pending = field; - if (!expression.validate()) pending = expression; - if (!value.validate()) pending = value; - if (!type.validate()) pending = type; - if (!children.validate()) pending = children; - if (pending == null) return true; - pending.wait(done); - return false; - } - - @Override - protected String getImageName() { - return ImageCache.IMG_VARIABLE; - } - - @Override public int compareTo(TCFNode n) { TCFNodeExpression e = (TCFNodeExpression)n; if (sort_pos < e.sort_pos) return -1; @@ -745,7 +934,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { done(node.script != null); return; } - if (!node.validateNode(this)) return; + if (!node.expression.validate(this)) return; if (node.expression.getData() != null && node.expression.getData().canAssign()) { if (TCFColumnPresentationExpression.COL_HEX_VALUE.equals(property)) { done(TCFNumberFormat.isValidHexNumber(node.toNumberString(16)) == null); @@ -769,7 +958,7 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { done(node.script); return; } - if (!node.validateNode(this)) return; + if (!node.value.validate(this)) return; if (node.value.getData() != null) { if (TCFColumnPresentationExpression.COL_HEX_VALUE.equals(property)) { done(node.toNumberString(16)); @@ -803,13 +992,14 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { done(Boolean.TRUE); return; } - if (!node.validateNode(this)) return; + if (!node.expression.validate(this)) return; if (node.expression.getData() != null && node.expression.getData().canAssign()) { byte[] bf = null; int size = node.expression.getData().getSize(); boolean is_float = false; boolean big_endian = false; boolean signed = false; + if (!node.value.validate(this)) return; IExpressions.Value eval = node.value.getData(); if (eval != null) { switch(eval.getTypeClass()) { @@ -847,7 +1037,6 @@ public class TCFNodeExpression extends TCFNode implements IElementEditor { else { node.value.reset(); node.addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); - node.model.fireModelChanged(); done(Boolean.TRUE); } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeLaunch.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeLaunch.java index f8779c235..3e446834b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeLaunch.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeLaunch.java @@ -16,7 +16,6 @@ import java.util.Arrays; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IMemory; import org.eclipse.tm.tcf.services.IRunControl; @@ -32,10 +31,7 @@ public class TCFNodeLaunch extends TCFNode { // Set initial selection in Debug View Protocol.invokeLater(new Runnable() { public void run() { - if (!children.validate()) { - children.wait(this); - return; - } + if (!children.validate(this)) return; ArrayList<TCFNodeStackFrame> frames = new ArrayList<TCFNodeStackFrame>(); TCFNode[] arr = children.toArray(); Arrays.sort(arr); @@ -54,20 +50,16 @@ public class TCFNodeLaunch extends TCFNode { } private boolean searchTopFrame(TCFNodeExecContext e, ArrayList<TCFNodeStackFrame> frames, Runnable r) { - if (!e.validateNode(r)) return false; - TCFNodeStackFrame f = e.getTopFrame(); + TCFChildrenStackTrace stack_trace = e.getStackTrace(); + if (!stack_trace.validate(r)) return false; + TCFNodeStackFrame f = stack_trace.getTopFrame(); if (f != null && !f.disposed) { frames.add(f); return true; } TCFChildrenExecContext c = e.getChildren(); - if (!c.validate()) { - c.wait(r); - return false; - } - TCFNode[] arr = c.toArray(); - Arrays.sort(arr); - for (TCFNode n : arr) { + if (!c.validate(r)) return false; + for (TCFNode n : c.toArray()) { if (!searchTopFrame((TCFNodeExecContext)n, frames, r)) return false; if (frames.size() > 0) break; } @@ -86,24 +78,15 @@ public class TCFNodeLaunch extends TCFNode { } @Override - public int getNodeIndex(IPresentationContext p, TCFNode n) { - if (!children.isValid()) return -1; - return children.getIndexOf(n); - } - - @Override - public int getChildrenCount(IPresentationContext p) { - if (!children.isValid()) return -1; - return children.size(); - } - - @Override - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { + if (!children.validate(done)) return false; result.setChildCount(children.size()); + return true; } @Override - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { + if (!children.validate(done)) return false; TCFNode[] arr = children.toArray(); int offset = 0; int r_offset = result.getOffset(); @@ -114,11 +97,14 @@ public class TCFNodeLaunch extends TCFNode { } offset++; } + return true; } @Override - protected void getData(IHasChildrenUpdate result) { + protected boolean getData(IHasChildrenUpdate result, Runnable done) { + if (!children.validate(done)) return false; result.setHasChilren(children.size() > 0); + return true; } void onContextAdded(IRunControl.RunControlContext context) { @@ -129,17 +115,7 @@ public class TCFNodeLaunch extends TCFNode { children.onContextAdded(context); } - int getContextCount() { - assert children.isValid(); - return children.size(); - } - - @Override - public boolean validateNode(Runnable done) { - if (!children.validate()) { - children.wait(done); - return false; - } - return true; + TCFChildrenExecContext getChildren() { + return children; } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeRegister.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeRegister.java index ae353f1ed..b7749e5fd 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeRegister.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeRegister.java @@ -55,10 +55,7 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { value = new TCFDataCache<byte[]>(channel) { @Override protected boolean startDataRetrieval() { - if (!context.validate()) { - context.wait(this); - return false; - } + if (!context.validate(this)) return false; IRegisters.RegistersContext ctx = context.getData(); if (ctx == null) { set(null, null, null); @@ -82,8 +79,14 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { } @Override - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); + protected boolean getData(ILabelUpdate result, Runnable done) { + TCFDataCache<?> pending = null; + if (!context.validate()) pending = context; + if (!value.validate()) pending = value; + if (pending != null) { + pending.wait(done); + return false; + } IRegisters.RegistersContext ctx = context.getData(); Throwable error = context.getError(); if (error != null) { @@ -140,6 +143,8 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { else { result.setLabel(id, 0); } + result.setImageDescriptor(ImageCache.getImageDescriptor(ImageCache.IMG_REGISTER), 0); + return true; } private void setLabel(ILabelUpdate result, int col, int radix) { @@ -234,23 +239,6 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); } - @Override - public boolean validateNode(Runnable done) { - TCFDataCache<?> pending = null; - if (!context.validate()) pending = context; - if (!value.validate()) pending = value; - if (pending != null) { - pending.wait(done); - return false; - } - return true; - } - - @Override - protected String getImageName() { - return ImageCache.IMG_REGISTER; - } - public CellEditor getCellEditor(IPresentationContext context, String column_id, Object element, Composite parent) { assert element == this; if (TCFColumnPresentationRegister.COL_HEX_VALUE.equals(column_id)) { @@ -268,7 +256,7 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { final TCFNodeRegister node = (TCFNodeRegister)element; return new TCFTask<Boolean>() { public void run() { - if (!node.validateNode(this)) return; + if (!node.context.validate(this)) return; if (node.context.getData() != null && node.context.getData().isWriteable()) { if (TCFColumnPresentationRegister.COL_HEX_VALUE.equals(property)) { done(TCFNumberFormat.isValidHexNumber(node.toNumberString(16)) == null); @@ -288,7 +276,7 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { final TCFNodeRegister node = (TCFNodeRegister)element; return new TCFTask<String>() { public void run() { - if (!node.validateNode(this)) return; + if (!node.value.validate(this)) return; if (node.value.getData() != null) { if (TCFColumnPresentationRegister.COL_HEX_VALUE.equals(property)) { done(node.toNumberString(16)); @@ -310,7 +298,7 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { new TCFTask<Boolean>() { public void run() { try { - if (!node.validateNode(this)) return; + if (!node.context.validate(this)) return; IRegisters.RegistersContext ctx = node.context.getData(); if (ctx != null && ctx.isWriteable()) { byte[] bf = null; @@ -338,7 +326,6 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor { else { node.value.reset(); node.addModelDelta(IModelDelta.STATE | IModelDelta.CONTENT); - node.model.fireModelChanged(); done(Boolean.TRUE); } } diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java index 85f273bb8..f5a67c76b 100644 --- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java +++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/model/TCFNodeStackFrame.java @@ -18,9 +18,9 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.swt.graphics.RGB; +import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.model.TCFSourceRef; import org.eclipse.tm.internal.tcf.debug.ui.ImageCache; import org.eclipse.tm.tcf.protocol.IChannel; @@ -40,6 +40,7 @@ public class TCFNodeStackFrame extends TCFNode { private final TCFChildrenExpressions children_exps; private final TCFDataCache<IStackTrace.StackTraceContext> stack_trace_context; private final TCFDataCache<TCFSourceRef> line_info; + private final TCFDataCache<BigInteger> address; TCFNodeStackFrame(final TCFNodeExecContext parent, final String id) { super(parent, id); @@ -51,7 +52,10 @@ public class TCFNodeStackFrame extends TCFNode { @Override protected boolean startDataRetrieval() { assert command == null; - if (!parent.isSuspended()) { + TCFDataCache<TCFContextState> parent_state_cache = parent.getState(); + if (!parent_state_cache.validate(this)) return false; + TCFContextState parent_state_data = parent_state_cache.getData(); + if (parent_state_data == null || !parent_state_data.is_suspended) { set(null, null, null); return true; } @@ -73,13 +77,11 @@ public class TCFNodeStackFrame extends TCFNode { line_info = new TCFDataCache<TCFSourceRef>(channel) { @Override protected boolean startDataRetrieval() { - if (!stack_trace_context.validate()) { - stack_trace_context.wait(this); - return false; - } - BigInteger n = getAddress(); + if (!stack_trace_context.validate(this)) return false; + if (!address.validate(this)) return false; + BigInteger n = address.getData(); if (n == null) { - set(null, null, null); + set(null, address.getError(), null); return true; } IMemory.MemoryContext mem_ctx = null; @@ -87,10 +89,7 @@ public class TCFNodeStackFrame extends TCFNode { while (p != null) { if (p instanceof TCFNodeExecContext) { TCFDataCache<IMemory.MemoryContext> cache = ((TCFNodeExecContext)p).getMemoryContext(); - if (!cache.validate()) { - cache.wait(this); - return false; - } + if (!cache.validate(this)) return false; mem_ctx = cache.getData(); if (mem_ctx != null) break; } @@ -133,6 +132,32 @@ public class TCFNodeStackFrame extends TCFNode { return false; } }; + address = new TCFDataCache<BigInteger>(channel) { + @Override + protected boolean startDataRetrieval() { + if (!stack_trace_context.validate(this)) return false; + IStackTrace.StackTraceContext ctx = stack_trace_context.getData(); + if (ctx != null) { + Number n = ctx.getInstructionAddress(); + if (n instanceof BigInteger) { + set(null, null, (BigInteger)n); + return true; + } + if (n != null) { + set(null, null, new BigInteger(n.toString())); + return true; + } + } + if (frame_no == 0) { + TCFDataCache<BigInteger> addr_cache = parent.getAddress(); + if (!addr_cache.validate(this)) return false; + set(null, addr_cache.getError(), addr_cache.getData()); + return true; + } + set(null, stack_trace_context.getError(), null); + return true; + } + }; } public int getFrameNo() { @@ -152,6 +177,7 @@ public class TCFNodeStackFrame extends TCFNode { void dispose() { stack_trace_context.reset(null); line_info.reset(null); + address.reset(null); children_regs.dispose(); children_vars.dispose(); children_exps.dispose(); @@ -169,18 +195,8 @@ public class TCFNodeStackFrame extends TCFNode { return stack_trace_context; } - @Override - public BigInteger getAddress() { - assert Protocol.isDispatchThread(); - if (!stack_trace_context.isValid()) return null; - IStackTrace.StackTraceContext ctx = stack_trace_context.getData(); - if (ctx != null) { - Number n = ctx.getInstructionAddress(); - if (n instanceof BigInteger) return (BigInteger)n; - if (n != null) return new BigInteger(n.toString()); - } - if (frame_no == 0) return parent.getAddress(); - return null; + public TCFDataCache<BigInteger> getAddress() { + return address; } public BigInteger getReturnAddress() { @@ -196,65 +212,38 @@ public class TCFNodeStackFrame extends TCFNode { } @Override - public int getNodeIndex(IPresentationContext p, TCFNode n) { - if (IDebugUIConstants.ID_REGISTER_VIEW.equals(p.getId())) { - if (!children_regs.isValid()) return -1; - return children_regs.getIndexOf(n); - } - if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(p.getId())) { - if (!children_vars.isValid()) return -1; - return children_vars.getIndexOf(n); - } - if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(p.getId())) { - if (!children_exps.isValid()) return -1; - return children_exps.getIndexOf(n); - } - return 0; - } - - @Override - public int getChildrenCount(IPresentationContext p) { - if (IDebugUIConstants.ID_REGISTER_VIEW.equals(p.getId())) { - if (!children_regs.isValid()) return -1; - return children_regs.size(); - } - if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(p.getId())) { - if (!children_vars.isValid()) return -1; - return children_vars.size(); - } - if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(p.getId())) { - if (!children_exps.isValid()) return -1; - return children_exps.size(); - } - return 0; - } - - @Override - protected void getData(IChildrenCountUpdate result) { + protected boolean getData(IChildrenCountUpdate result, Runnable done) { if (IDebugUIConstants.ID_REGISTER_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_regs.validate(done)) return false; result.setChildCount(children_regs.size()); } else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_vars.validate(done)) return false; result.setChildCount(children_vars.size()); } else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_exps.validate(done)) return false; result.setChildCount(children_exps.size()); } else { result.setChildCount(0); } + return true; } @Override - protected void getData(IChildrenUpdate result) { + protected boolean getData(IChildrenUpdate result, Runnable done) { TCFNode[] arr = null; if (IDebugUIConstants.ID_REGISTER_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_regs.validate(done)) return false; arr = children_regs.toArray(); } else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_vars.validate(done)) return false; arr = children_vars.toArray(); } else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_exps.validate(done)) return false; arr = children_exps.toArray(); } else { @@ -269,35 +258,48 @@ public class TCFNodeStackFrame extends TCFNode { } offset++; } + return true; } @Override - protected void getData(IHasChildrenUpdate result) { + protected boolean getData(IHasChildrenUpdate result, Runnable done) { if (IDebugUIConstants.ID_REGISTER_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_regs.validate(done)) return false; result.setHasChilren(children_regs.size() > 0); } else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_vars.validate(done)) return false; result.setHasChilren(children_vars.size() > 0); } else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(result.getPresentationContext().getId())) { + if (!children_exps.validate(done)) return false; result.setHasChilren(children_exps.size() > 0); } else { result.setHasChilren(false); } + return true; } @Override - protected void getData(ILabelUpdate result) { - result.setImageDescriptor(ImageCache.getImageDescriptor(getImageName()), 0); - TCFChildrenStackTrace st = ((TCFNodeExecContext)parent).getStackTrace(); - if (st.getData().get(id) == null) { + protected boolean getData(ILabelUpdate result, Runnable done) { + String image_name = null; + TCFChildrenStackTrace stack_trace_cache = ((TCFNodeExecContext)parent).getStackTrace(); + if (!stack_trace_cache.validate(done)) return false; + if (stack_trace_cache.getData().get(id) == null) { result.setLabel("", 0); } else { + TCFDataCache<TCFContextState> state_cache = ((TCFNodeExecContext)parent).getState(); + if (!state_cache.validate(done)) return false; + TCFContextState state_data = state_cache.getData(); + if (state_data != null && state_data.is_suspended) image_name = ImageCache.IMG_STACK_FRAME_SUSPENDED; + else image_name = ImageCache.IMG_STACK_FRAME_RUNNING; + if (!stack_trace_context.validate(done)) return false; + if (!line_info.validate(done)) return false; Throwable error = stack_trace_context.getError(); if (error == null) error = line_info.getError(); - if (error != null && ((TCFNodeExecContext)parent).isSuspended()) { + if (error != null && state_data != null && state_data.is_suspended) { result.setForeground(new RGB(255, 0, 0), 0); result.setLabel(error.getClass().getName() + ": " + error.getMessage(), 0); } @@ -315,6 +317,8 @@ public class TCFNodeStackFrame extends TCFNode { } } } + result.setImageDescriptor(ImageCache.getImageDescriptor(image_name), 0); + return true; } private String makeHexAddrString(IMemory.MemoryContext m, Number n) { @@ -337,6 +341,7 @@ public class TCFNodeStackFrame extends TCFNode { void onSuspended() { stack_trace_context.reset(); line_info.reset(); + address.reset(); children_regs.onSuspended(); children_vars.onSuspended(); children_exps.onSuspended(); @@ -349,27 +354,6 @@ public class TCFNodeStackFrame extends TCFNode { } @Override - public boolean validateNode(Runnable done) { - TCFDataCache<?> pending = null; - TCFChildrenStackTrace stack_trace = ((TCFNodeExecContext)parent).getStackTrace(); - if (!stack_trace.validate()) pending = stack_trace; - if (!stack_trace_context.validate()) pending = stack_trace_context; - if (!children_regs.validate()) pending = children_regs; - if (!children_vars.validate()) pending = children_vars; - if (!children_exps.validate()) pending = children_exps; - if (!line_info.validate()) pending = line_info; - if (pending == null) return true; - pending.wait(done); - return false; - } - - @Override - protected String getImageName() { - if (((TCFNodeExecContext)parent).isRunning()) return ImageCache.IMG_STACK_FRAME_RUNNING; - return ImageCache.IMG_STACK_FRAME_SUSPENDED; - } - - @Override public int compareTo(TCFNode n) { if (n instanceof TCFNodeStackFrame) { TCFNodeStackFrame f = (TCFNodeStackFrame)n; diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepInto.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepInto.java index 40735ad34..26e48c26d 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepInto.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepInto.java @@ -16,8 +16,6 @@ import org.eclipse.tm.tcf.util.TCFDataCache; public abstract class TCFActionStepInto extends TCFAction implements IRunControl.RunControlListener { - private static final long TIMEOUT = 10000; - private final boolean src_step; private final IRunControl rc = launch.getService(IRunControl.class); @@ -52,18 +50,8 @@ public abstract class TCFActionStepInto extends TCFAction implements IRunControl exit(new Exception("Invalid context ID")); return; } - if (!ctx.canResume(src_step ? IRunControl.RM_STEP_INTO_LINE : IRunControl.RM_STEP_INTO)) { - Protocol.invokeLater(TIMEOUT, new Runnable() { - public void run() { - exit(new Exception("Time out")); - } - }); - } - } - if (!state.validate()) { - state.wait(this); - return; } + if (!state.validate(this)) return; if (!state.getData().is_suspended) { exit(new Exception("Context is not suspended")); return; @@ -83,16 +71,14 @@ public abstract class TCFActionStepInto extends TCFAction implements IRunControl return; } TCFDataCache<?> stack_trace = getStackTrace(); - if (!stack_trace.validate()) { - stack_trace.wait(this); + if (!stack_trace.validate(this)) return; + if (stack_trace.getData() == null) { + exit(stack_trace.getError()); return; } if (source_ref == null) { line_info = getLineInfo(); - if (!line_info.validate()) { - line_info.wait(this); - return; - } + if (!line_info.validate(this)) return; source_ref = line_info.getData(); if (source_ref == null) { exit(new Exception("Line info not available")); @@ -117,10 +103,7 @@ public abstract class TCFActionStepInto extends TCFAction implements IRunControl } if (step_cnt > 0) { TCFDataCache<IStackTrace.StackTraceContext> frame = getStackFrame(); - if (!frame.validate()) { - frame.wait(this); - return; - } + if (!frame.validate(this)) return; Number addr = frame.getData().getInstructionAddress(); BigInteger pc = addr instanceof BigInteger ? (BigInteger)addr : new BigInteger(addr.toString()); if (pc == null || pc0 == null || pc1 == null) { @@ -128,10 +111,7 @@ public abstract class TCFActionStepInto extends TCFAction implements IRunControl return; } if (pc.compareTo(pc0) < 0 || pc.compareTo(pc1) >= 0) { - if (!line_info.validate()) { - line_info.wait(this); - return; - } + if (!line_info.validate(this)) return; TCFSourceRef ref = line_info.getData(); if (ref != null && ref.area != null) { if (isSameLine(source_ref.area, ref.area)) { diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOut.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOut.java index d4c598c7f..962d913ea 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOut.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOut.java @@ -6,7 +6,6 @@ import java.util.Map; import org.eclipse.tm.internal.tcf.debug.model.TCFContextState; import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; import org.eclipse.tm.tcf.protocol.IToken; -import org.eclipse.tm.tcf.protocol.Protocol; import org.eclipse.tm.tcf.services.IBreakpoints; import org.eclipse.tm.tcf.services.IRunControl; import org.eclipse.tm.tcf.services.IStackTrace; @@ -15,8 +14,6 @@ import org.eclipse.tm.tcf.util.TCFDataCache; public abstract class TCFActionStepOut extends TCFAction implements IRunControl.RunControlListener { - private static final long TIMEOUT = 10000; - private final IRunControl rc = launch.getService(IRunControl.class); private final IBreakpoints bps = launch.getService(IBreakpoints.class); @@ -46,18 +43,8 @@ public abstract class TCFActionStepOut extends TCFAction implements IRunControl. exit(new Exception("Invalid context ID")); return; } - if (!ctx.canResume(IRunControl.RM_STEP_OUT)) { - Protocol.invokeLater(TIMEOUT, new Runnable() { - public void run() { - exit(new Exception("Time out")); - } - }); - } - } - if (!state.validate()) { - state.wait(this); - return; } + if (!state.validate(this)) return; if (!state.getData().is_suspended) { exit(new Exception("Context is not suspended")); return; @@ -73,10 +60,7 @@ public abstract class TCFActionStepOut extends TCFAction implements IRunControl. return; } TCFDataCache<?> stack_trace = getStackTrace(); - if (!stack_trace.validate()) { - stack_trace.wait(this); - return; - } + if (!stack_trace.validate(this)) return; if (getStackFrameIndex() < 0) { // Stepped out of selected function exit(null); @@ -84,17 +68,16 @@ public abstract class TCFActionStepOut extends TCFAction implements IRunControl. else if (bps != null && ctx.canResume(IRunControl.RM_RESUME)) { if (bp == null) { TCFDataCache<IStackTrace.StackTraceContext> frame = getStackFrame(); - if (!frame.validate()) { - frame.wait(this); - return; - } + if (!frame.validate(this)) return; Number addr = frame.getData().getReturnAddress(); if (addr == null) { exit(new Exception("Unknown stack frame return address")); return; } + String id = "Step." + ctx.getID(); + launch.addContextActionBreakpoint(id, "Step"); bp = new HashMap<String,Object>(); - bp.put(IBreakpoints.PROP_ID, "Step" + System.currentTimeMillis()); + bp.put(IBreakpoints.PROP_ID, id); bp.put(IBreakpoints.PROP_LOCATION, addr.toString()); bp.put(IBreakpoints.PROP_CONDITION, "$thread==\"" + ctx.getID() + "\""); bp.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); @@ -162,8 +145,7 @@ public abstract class TCFActionStepOut extends TCFAction implements IRunControl. public void contextResumed(String context) { } - public void contextSuspended(String context, String pc, String reason, - Map<String, Object> params) { + public void contextSuspended(String context, String pc, String reason, Map<String,Object> params) { if (!context.equals(ctx.getID())) return; exit(null); } diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOver.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOver.java index 0d4a28ff0..d66383cd1 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOver.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/actions/TCFActionStepOver.java @@ -18,8 +18,6 @@ import org.eclipse.tm.tcf.util.TCFDataCache; public abstract class TCFActionStepOver extends TCFAction implements IRunControl.RunControlListener { - private static final long TIMEOUT = 10000; - private final boolean src_step; private final IRunControl rc = launch.getService(IRunControl.class); private final IBreakpoints bps = launch.getService(IBreakpoints.class); @@ -56,18 +54,8 @@ public abstract class TCFActionStepOver extends TCFAction implements IRunControl exit(new Exception("Invalid context ID")); return; } - if (!ctx.canResume(src_step ? IRunControl.RM_STEP_OVER_LINE : IRunControl.RM_STEP_OVER)) { - Protocol.invokeLater(TIMEOUT, new Runnable() { - public void run() { - exit(new Exception("Time out")); - } - }); - } - } - if (!state.validate()) { - state.wait(this); - return; } + if (!state.validate(this)) return; if (!state.getData().is_suspended) { exit(new Exception("Context is not suspended")); return; @@ -83,16 +71,10 @@ public abstract class TCFActionStepOver extends TCFAction implements IRunControl return; } TCFDataCache<?> stack_trace = getStackTrace(); - if (!stack_trace.validate()) { - stack_trace.wait(this); - return; - } + if (!stack_trace.validate(this)) return; if (src_step && source_ref == null) { line_info = getLineInfo(); - if (!line_info.validate()) { - line_info.wait(this); - return; - } + if (!line_info.validate(this)) return; source_ref = line_info.getData(); if (source_ref == null) { exit(new Exception("Line info not available")); @@ -125,17 +107,16 @@ public abstract class TCFActionStepOver extends TCFAction implements IRunControl else if (bps != null && ctx.canResume(IRunControl.RM_RESUME)) { if (bp == null) { TCFDataCache<IStackTrace.StackTraceContext> frame = getStackFrame(); - if (!frame.validate()) { - frame.wait(this); - return; - } + if (!frame.validate(this)) return; Number addr = frame.getData().getInstructionAddress(); if (addr == null) { exit(new Exception("Unknown PC address")); return; } + String id = "Step." + ctx.getID(); + launch.addContextActionBreakpoint(id, "Step"); bp = new HashMap<String,Object>(); - bp.put(IBreakpoints.PROP_ID, "Step" + System.currentTimeMillis()); + bp.put(IBreakpoints.PROP_ID, id); bp.put(IBreakpoints.PROP_LOCATION, addr.toString()); bp.put(IBreakpoints.PROP_CONDITION, "$thread==\"" + ctx.getID() + "\""); bp.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE); @@ -172,10 +153,7 @@ public abstract class TCFActionStepOver extends TCFAction implements IRunControl assert src_step; BigInteger pc = new BigInteger(state.getData().suspend_pc); if (pc.compareTo(pc0) < 0 || pc.compareTo(pc1) >= 0) { - if (!line_info.validate()) { - line_info.wait(this); - return; - } + if (!line_info.validate(this)) return; TCFSourceRef ref = line_info.getData(); if (ref != null && ref.area != null) { if (isSameLine(source_ref.area, ref.area)) { diff --git a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFLaunch.java b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFLaunch.java index 4ee4715dc..113354bea 100644 --- a/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFLaunch.java +++ b/plugins/org.eclipse.tm.tcf.debug/src/org/eclipse/tm/internal/tcf/debug/model/TCFLaunch.java @@ -82,8 +82,8 @@ public class TCFLaunch extends Launch { private int process_exit_code; private int context_action_cnt; - private final HashMap<String,LinkedList<Runnable>> context_action_queue = - new HashMap<String,LinkedList<Runnable>>(); + private final HashMap<String,LinkedList<Runnable>> context_action_queue = new HashMap<String,LinkedList<Runnable>>(); + private final HashMap<String,String> context_action_bps = new HashMap<String,String>(); private HashMap<String,String> stream_ids = new HashMap<String,String>(); @@ -678,7 +678,11 @@ public class TCFLaunch extends Launch { } } - public boolean hasPendingContextActions() { - return context_action_cnt > 0; + public void addContextActionBreakpoint(String id, String type) { + context_action_bps.put(id, type); + } + + public String getContextActionBreakpoint(String id) { + return context_action_bps.get(id); } } diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFSourceLookupParticipant.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFSourceLookupParticipant.java index 136a95efc..f3ff43613 100644 --- a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFSourceLookupParticipant.java +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFSourceLookupParticipant.java @@ -30,14 +30,8 @@ public class TCFDSFSourceLookupParticipant extends TCFSourceLookupParticipant { Protocol.invokeLater(new Runnable() { public void run() { TCFFrameDMC dmc = (TCFFrameDMC)object; - if (!dmc.context_cache.validate()) { - dmc.context_cache.wait(this); - return; - } - if (!dmc.source_cache.validate()) { - dmc.source_cache.wait(this); - return; - } + if (!dmc.context_cache.validate(this)) return; + if (!dmc.source_cache.validate(this)) return; synchronized (res) { TCFSourceRef ref = dmc.source_cache.getData(); if (ref != null) res[0] = ref.area; diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java index 7cf0d0731..fd3b85310 100644 --- a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java @@ -109,10 +109,7 @@ public abstract class TCFDSFExecutionDMC extends AbstractDMContext @Override public boolean startDataRetrieval() { assert command == null; - if (!run_control_context_cache.validate()) { - run_control_state_cache.wait(this); - return false; - } + if (!run_control_context_cache.validate(this)) return false; RunControlContext c = run_control_context_cache.getData(); if (c == null || !c.hasState()) { reset(null); diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java index f281fdb18..c7e10f766 100644 --- a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java @@ -81,10 +81,7 @@ public class TCFDSFStack extends AbstractDsfService implements IStack { @Override protected boolean startDataRetrieval() { - if (!context_cache.validate()) { - context_cache.wait(this); - return false; - } + if (!context_cache.validate(this)) return false; IStackTrace.StackTraceContext ctx = context_cache.getData(); Number n = ctx.getInstructionAddress(); BigInteger a = null; |