blob: 99f0ece0bf76ad7ce83ead9d7dec8c429a6ecf27 [file] [log] [blame]
package org.jetbrains.debugger;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.AtomicReference;
public abstract class SuspendContextManagerBase<T extends SuspendContextBase, CALL_FRAME extends CallFrame> implements SuspendContextManager<CALL_FRAME> {
protected final AtomicReference<T> context = new AtomicReference<T>();
protected final AtomicReference<ActionCallback> suspendCallback = new AtomicReference<ActionCallback>();
public final void setContext(@NotNull T newContext) {
if (!context.compareAndSet(null, newContext)) {
throw new IllegalStateException("Attempt to set context, but current suspend context is already exists");
}
}
public final void contextDismissed(@NotNull T context, @NotNull DebugEventListener listener) {
if (!this.context.compareAndSet(context, null)) {
throw new IllegalStateException("Expected " + context + ", but another suspend context exists");
}
context.getValueManager().markObsolete();
listener.resumed();
}
@Nullable
@Override
public final T getContext() {
return context.get();
}
@NotNull
@Override
public T getContextOrFail() {
T context = getContext();
if (context == null) {
throw new IllegalStateException("No current suspend context");
}
return context;
}
@NotNull
@Override
public final ActionCallback suspend() {
ActionCallback callback = suspendCallback.get();
if (callback != null) {
return callback;
}
if (context.get() != null) {
return ActionCallback.DONE;
}
callback = new ActionCallback();
doSuspend(callback).notifyWhenRejected(callback);
return callback;
}
protected abstract ActionCallback doSuspend(ActionCallback callback);
@Override
public boolean isContextObsolete(@NotNull SuspendContext context) {
return this.context.get() != context;
}
@Override
public void setOverlayMessage(@Nullable String message) {
}
@NotNull
@Override
public final AsyncResult<Boolean> restartFrame(@NotNull CALL_FRAME callFrame) {
return restartFrame(callFrame, getContextOrFail());
}
@NotNull
protected abstract AsyncResult<Boolean> restartFrame(@NotNull CALL_FRAME callFrame, @NotNull T currentContext);
}