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); } }