blob: 5505766e28b84fead722a705970bb3afac5dd279 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2019 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* CEA LIST - Initial API and implementation
* CEA LIST - Bug 551906
*
*****************************************************************************/
package org.eclipse.papyrus.moka.debug.target;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IBreakpoint;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.papyrus.moka.kernel.SuspensionReasons;
public class ExecutionEngineThread extends ExecutionEngineDebugElement implements IExecutionEngineThread {
/**
* ID of the UML debug model
*/
public static final String MODEL_ID = "org.eclipse.papyrus.moka.kernel.debug.model";
/**
* ID of the thread running the active object
*/
private String id;
/**
* The suspension reason
*/
private SuspensionReasons suspensionReason;
/**
* The stack frame of the thread
*/
private ExecutionEngineStackFrame stackFrame;
public ExecutionEngineThread(IDebugTarget target) {
super(target);
status = DebugElementStatus.RUNNING;
statusLock = new ReentrantLock(true);
stackFrame = new ExecutionEngineStackFrame(this);
}
/**
* @see IDebugTarget#canResume()
*
* A thread can only be resumed if it has the suspended state
*/
@Override
public boolean canResume() {
return getStatus().equals(DebugElementStatus.SUSPENDED);
}
/**
* @see IThread#resume()
*
* Resume the corresponding execution engine thread
*
* An explicit call to resume always occurs as a client (i.e., the user
* hits the resume button)
*/
@Override
public void resume() throws DebugException {
IExecutionEngineDebugTarget target = (IExecutionEngineDebugTarget) getDebugTarget();
if (target != null) {
IExecutionEngineDebugTargetClient client = target.getClient();
if (client != null) {
client.fireResumeThreadEvent(this);
this.suspensionReason = SuspensionReasons.NONE;
}
}
}
/**
* @see IDebugTarget#canSuspend()
*
* A thread can only be suspended if it has the running state
*/
@Override
public boolean canSuspend() {
return getStatus().equals(DebugElementStatus.RUNNING);
}
/**
* @see IExecutionEngineThread#isSuspended()
*
* A thread is suspended if it has the suspended state
*/
@Override
public boolean isSuspended() {
return getStatus().equals(DebugElementStatus.SUSPENDED);
}
/**
* @see IThread#suspend()
*
* Suspend the corresponding execution engine thread
*
* An explicit call to suspend always occurs as a client request (i.e., the
* user hits the pause button in the interface)
*/
@Override
public void suspend() throws DebugException {
IExecutionEngineDebugTarget target = (IExecutionEngineDebugTarget) getDebugTarget();
if (target != null) {
IExecutionEngineDebugTargetClient client = target.getClient();
if (client != null) {
client.fireSuspendThreadEvent(this);
setStatus(DebugElementStatus.SUSPENDED);
}
}
}
/**
* @see IThread#suspend()
*
* Handle an execution engine request specifying that the thread was
* suspended.
*/
@Override
public void handleSuspendEvent(int supensionDetail) {
if (canSuspend()) {
setStatus(DebugElementStatus.SUSPENDED);
fireSuspendEvent(supensionDetail);
}
}
/**
* @see IDebugTarget#canTerminate()
*
* A thread can terminate if it either running or suspended
*/
@Override
public boolean canTerminate() {
return getStatus().equals(DebugElementStatus.RUNNING) || getStatus().equals(DebugElementStatus.SUSPENDED);
}
/**
* @see IDebugTarget#isTerminated()
*
* A thread is terminated when it has the terminated state
*/
@Override
public boolean isTerminated() {
return getStatus().equals(DebugElementStatus.TERMINATED);
}
/**
* @see IDebugTarget#terminate()
*
* Terminate the corresponding execution engine thread. If the thread is
* suspended then it is resumed before termination.
*
* An explicit call to terminate always occurs as a client request (i.e.,
* the user hits the pause button in the interface)
*/
@Override
public void terminate() throws DebugException {
IExecutionEngineDebugTarget target = (IExecutionEngineDebugTarget) getDebugTarget();
if (target != null) {
IExecutionEngineDebugTargetClient client = target.getClient();
if (client != null) {
if (isSuspended()) {
resume();
}
client.fireTerminateThreadEvent(this);
}
}
}
@Override
public boolean canStepInto() {
return false;
}
@Override
public boolean canStepOver() {
return false;
}
@Override
public boolean canStepReturn() {
return false;
}
@Override
public boolean isStepping() {
return false;
}
@Override
public void stepInto() throws DebugException {
}
@Override
public void stepOver() throws DebugException {
}
@Override
public void stepReturn() throws DebugException {
}
@Override
public String getModelIdentifier() {
return MODEL_ID;
}
/**
*
*/
@Override
public IStackFrame[] getStackFrames() throws DebugException {
if (isSuspended()) {
return new IStackFrame[] { stackFrame };
}
return new IStackFrame[0];
}
/**
* {@link IThread#hasStackFrames()}
*
* A thread can only have stack frames when it is suspended
*/
@Override
public boolean hasStackFrames() throws DebugException {
return isSuspended();
}
/**
* {@link IThread#getTopStackFrame()}
*
* @return the top stack frame if the thread is suspended and false otherwise
*/
@Override
public IStackFrame getTopStackFrame() throws DebugException {
IStackFrame top = null;
if (isSuspended()) {
top = stackFrame;
}
return top;
}
@Override
public int getPriority() throws DebugException {
return 0;
}
@Override
public String getName() throws DebugException {
return id;
}
@Override
public IBreakpoint[] getBreakpoints() {
return null;
}
@Override
public String getID() {
return id;
}
public void setID(String id) {
this.id = id;
}
public SuspensionReasons getSuspensionReason() {
return suspensionReason;
}
public void setSuspensionReason(SuspensionReasons suspensionReason) {
this.suspensionReason = suspensionReason;
}
}