package jetbrains.mps.debugger.java.runtime.engine.events;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import com.sun.jdi.ObjectCollectedException;
import com.sun.jdi.InternalException;
import com.sun.jdi.request.EventRequest;
import org.apache.log4j.Level;
import org.jetbrains.annotations.Nullable;
import com.sun.jdi.ThreadReference;
import jetbrains.mps.internal.collections.runtime.IWhereFilter;
public class ContextManager {
private static final Logger LOG = LogManager.getLogger(ContextManager.class);
private final List<EventContext> mySuspendedContexts = ListSequence.fromList(new ArrayList<EventContext>());
private UserContext myUserContext;
public ContextManager() {
}
/*package*/ synchronized boolean votePause(EventContext context) {
context.vote();
ListSequence.fromList(mySuspendedContexts).insertElement(0, context);
return context.isProcessed();
}
/*package*/ synchronized void voteResume(EventContext context) {
context.vote();
if (context.isProcessed() && !(ListSequence.fromList(mySuspendedContexts).contains(context))) {
resume(context);
}
}
/*package*/ void pauseUserContext(UserContext context) {
myUserContext = context;
}
/*package*/ synchronized void resume(Context context) {
if (context instanceof EventContext) {
assert ((EventContext) context).isProcessed();
ListSequence.fromList(mySuspendedContexts).removeElement((EventContext) context);
tryResume5Times((EventContext) context, new _FunctionTypes._void_P1_E0<EventContext>() {
public void invoke(EventContext c) {
c.resume();
}
});
} else if (context instanceof UserContext) {
assert myUserContext == context;
myUserContext = null;
// I do not want to have resume method in the interface and do not want to create a class
tryResume5Times(((UserContext) context), new _FunctionTypes._void_P1_E0<UserContext>() {
public void invoke(UserContext c) {
c.resume();
}
});
} else {
assert false : "Do not know what kind of context it is " + context;
}
}
private <C extends Context> void tryResume5Times(C context, _FunctionTypes._void_P1_E0<? super C> resume) {
int resumeAttempts = 5;
while (--resumeAttempts > 0) {
try {
resume.invoke(context);
break;
} catch (ObjectCollectedException e) {
// according to error reports set.resume() may throw this if one of the threads has been collected
} catch (InternalException e) {
// InternalException 13 means that there are running threads that we are trying to resume
// On MacOS it happened that native thread didn't stop while some java thread reached breakpoint
if (e.errorCode() == 13 && context.getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
// Patches.MAC_RESUME_VM_HACK &&
// Its funny, but second resume solves the problem
} else {
if (LOG.isEnabledFor(Level.ERROR)) {
LOG.error("", e);
}
break;
}
}
}
}
@Nullable
public synchronized Context firstContext() {
if (myUserContext != null) {
return myUserContext;
}
if (ListSequence.fromList(mySuspendedContexts).isNotEmpty()) {
ListSequence.fromList(mySuspendedContexts).first();
}
return null;
}
@Nullable
public synchronized Context findContextForThread(final ThreadReference threadReference) {
EventContext context = ListSequence.fromList(mySuspendedContexts).findFirst(new IWhereFilter<EventContext>() {
public boolean accept(EventContext it) {
return eq_toclu7_a0a0a0a0a0a0a01(it.getThread(), threadReference);
}
});
if (context != null) {
return context;
}
context = ListSequence.fromList(mySuspendedContexts).findFirst(new IWhereFilter<EventContext>() {
public boolean accept(EventContext it) {
return it.getSuspendPolicy() == EventRequest.SUSPEND_ALL;
}
});
if (context != null) {
return context;
}
if (myUserContext != null) {
return myUserContext;
}
return null;
}
public synchronized boolean isPausedOnEvent(Context context) {
return ListSequence.fromList(mySuspendedContexts).contains(context);
}
private static boolean eq_toclu7_a0a0a0a0a0a0a01(Object a, Object b) {
return (a != null ? a.equals(b) : a == b);
}
}