Files
openide/source/com/intellij/debugger/jdi/ThreadReferenceProxyImpl.java
T
2005-03-29 16:58:58 +04:00

195 lines
6.5 KiB
Java

/*
* @author Eugene Zhuravlev
*/
package com.intellij.debugger.jdi;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.jdi.ThreadReferenceProxy;
import com.intellij.openapi.diagnostic.Logger;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
public final class ThreadReferenceProxyImpl extends ObjectReferenceProxyImpl implements ThreadReferenceProxy {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.jdi.ThreadReferenceProxyImpl");
// cached data
private String myName;
private int myFrameCount = -1;
// stackframes, 0 - bottom
private List<StackFrameProxyImpl> myFramesFromBottom = new ArrayList<StackFrameProxyImpl>();
//cache build on the base of myFramesFromBottom 0 - top, initially nothing is cached
private List<StackFrameProxyImpl> myFrames = null;
private ThreadGroupReferenceProxyImpl myThreadGroupProxy;
public static Comparator<ThreadReferenceProxyImpl> ourComparator = new Comparator<ThreadReferenceProxyImpl>() {
public int compare(ThreadReferenceProxyImpl th1, ThreadReferenceProxyImpl th2) {
return th1.name().compareTo(th2.name());
}
};
public ThreadReferenceProxyImpl(VirtualMachineProxyImpl virtualMachineProxy, ThreadReference threadReference) {
super(virtualMachineProxy, threadReference);
LOG.assertTrue(threadReference != null);
}
public ThreadReference getThreadReference() {
DebuggerManagerThreadImpl.assertIsManagerThread();
return (ThreadReference)getObjectReference();
}
public VirtualMachineProxyImpl getVirtualMachine() {
DebuggerManagerThreadImpl.assertIsManagerThread();
return (VirtualMachineProxyImpl) myTimer;
}
public String name() {
checkValid();
if (myName == null) {
myName = getThreadReference().name();
}
return myName;
}
public int getSuspendCount() {
DebuggerManagerThreadImpl.assertIsManagerThread();
//LOG.assertTrue((mySuspendCount > 0) == suspends());
return getThreadReference().suspendCount();
}
public void suspend() {
DebuggerManagerThreadImpl.assertIsManagerThread();
getThreadReference().suspend();
clearCaches();
}
public String toString() {
return "ThreadReferenceProxyImpl: " + getThreadReference().toString() + " " + super.toString();
}
public void resume() {
DebuggerManagerThreadImpl.assertIsManagerThread();
//JDI clears all caches on thread resume !!
if(LOG.isDebugEnabled()) {
LOG.debug("before resume" + getThreadReference());
}
getVirtualMachineProxy().clearCaches();
getThreadReference().resume();
}
protected void clearCaches() {
DebuggerManagerThreadImpl.assertIsManagerThread();
myFrames = null;
myFrameCount = -1;
super.clearCaches();
}
public int suspendCount() {
DebuggerManagerThreadImpl.assertIsManagerThread();
return getThreadReference().suspendCount();
}
public int status() {
return getThreadReference().status();
}
public ThreadGroupReferenceProxyImpl threadGroupProxy() {
DebuggerManagerThreadImpl.assertIsManagerThread();
checkValid();
if(myThreadGroupProxy == null) {
myThreadGroupProxy = getVirtualMachineProxy().getThreadGroupReferenceProxy(getThreadReference().threadGroup());
}
return myThreadGroupProxy;
}
public int frameCount() throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
checkValid();
if (myFrameCount == -1) {
try {
final ThreadReference threadReference = getThreadReference();
myFrameCount = threadReference.frameCount();
}
catch (IncompatibleThreadStateException e) {
if (!isSuspended()) {
// give up because it seems to be really resumed
throw EvaluateExceptionUtil.createEvaluateException(e);
}
else {
// JDI bug: although isSuspended() == true, frameCount() may throw IncompatibleTharedStateException
// unfortunately, impossible to get this information at the moment, so assume the frame count is null
myFrameCount = 0;
}
}
}
return myFrameCount;
}
public List<StackFrameProxyImpl> frames() throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
LOG.assertTrue(getThreadReference().isSuspended());
checkValid();
if(myFrames == null) {
checkFrames();
myFrames = new ArrayList<StackFrameProxyImpl>(frameCount());
for (ListIterator<StackFrameProxyImpl> iterator = myFramesFromBottom.listIterator(frameCount()); iterator.hasPrevious();) {
StackFrameProxyImpl stackFrameProxy = iterator.previous();
myFrames.add(stackFrameProxy);
}
}
return myFrames;
}
private void checkFrames() throws EvaluateException {
if (myFramesFromBottom.size() < frameCount()) {
int count = frameCount();
List<StackFrame> frames = null;
try {
frames = getThreadReference().frames(0, count - myFramesFromBottom.size());
}
catch (IncompatibleThreadStateException e) {
throw EvaluateExceptionUtil.createEvaluateException(e);
}
int index = myFramesFromBottom.size() + 1;
for (ListIterator<StackFrame> iterator = frames.listIterator(count - myFramesFromBottom.size()); iterator.hasPrevious();) {
StackFrame stackFrame = iterator.previous();
myFramesFromBottom.add(new StackFrameProxyImpl(this, stackFrame, index));
index++;
}
}
}
public StackFrameProxyImpl frame(int i) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
if(!getThreadReference().isSuspended()) return null;
checkFrames();
return myFramesFromBottom.get(frameCount() - i - 1);
}
public void popFrames(StackFrameProxyImpl stackFrame) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
getThreadReference().popFrames(stackFrame.getStackFrame());
}
catch (IncompatibleThreadStateException e) {
throw EvaluateExceptionUtil.createEvaluateException(e);
}
clearCaches();
}
public boolean isSuspended() {
DebuggerManagerThreadImpl.assertIsManagerThread();
return getThreadReference().isSuspended();
}
}