package org.matheclipse.core.eval;
import java.io.Writer;
import org.matheclipse.core.basic.Config;
import org.matheclipse.core.eval.exception.TimeExceeded;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.form.output.OutputFormFactory;
import org.matheclipse.core.interfaces.IExpr;
/**
* Run the evaluation of a given math formula String in a time
* limited thread
*/
public class TimeConstrainedEvaluator extends EvalUtilities implements Runnable {
protected IExpr fEvaluationResult;
protected Throwable fException;
protected IExpr fParsedExpression;
private long fMilliSeconds;
private final boolean fRelaxedSyntax;
private boolean fTraceEvaluation;
public TimeConstrainedEvaluator(final EvalEngine evalEngine, final boolean msie, final long milliSeconds) {
this(evalEngine, msie, milliSeconds, false);
}
public TimeConstrainedEvaluator(final EvalEngine evalEngine, final boolean msie, final long milliSeconds, boolean relaxedSyntax) {
super(evalEngine, msie, relaxedSyntax);
fMilliSeconds = milliSeconds;
fRelaxedSyntax = relaxedSyntax;
fTraceEvaluation = false;
}
public void run() {
try {
startRequest();
if (fTraceEvaluation) {
fEvaluationResult = evalTrace(fParsedExpression, null, F.List());
} else {
fEvaluationResult = evaluate(fParsedExpression);
}
} catch (final Exception e) {
if (Config.DEBUG) {
e.printStackTrace();
}
fException = e;
} catch (final OutOfMemoryError e) {
if (Config.DEBUG) {
e.printStackTrace();
}
fEvaluationResult = F.stringx("OutOfMemoryError");
// fException = e;
} catch (final StackOverflowError e) {
if (Config.DEBUG) {
e.printStackTrace();
}
fEvaluationResult = F.stringx("StackOverflowError");
// fException = e;
}
}
/**
* Runs the evaluation of the given math formula String in a time
* limited thread
*
* @param traceEvaluation
*
*/
public IExpr constrainedEval(final Writer writer, final String inputString, boolean traceEvaluation) throws Exception {
fEvaluationResult = null;
fException = null;
fParsedExpression = null;
fEvalEngine.setStopRequested(false);
fTraceEvaluation = traceEvaluation;
try {
EvalEngine.set(fEvalEngine);
fParsedExpression = fEvalEngine.parse(inputString);
} catch (final RuntimeException e) {
throw e;
}
return constrainedEval(writer, fParsedExpression);
}
/**
* Runs the evaluation of the given math expression in a time limited thread
*
*/
public IExpr constrainedEval(final Writer writer, final IExpr inputExpression) throws Exception {
fEvaluationResult = null;
fException = null;
fParsedExpression = inputExpression;
fEvalEngine.setStopRequested(false);
try {
final Thread thread = new Thread(this, "TimeConstrainedEvaluator");// EvaluationRunnable();
thread.start();
thread.join(fMilliSeconds);
if (thread.isAlive()) {
thread.interrupt();
fEvalEngine.stopRequest();
// wait a bit, so the thread can stop by itself
Thread.sleep(Config.TIME_CONSTRAINED_SLEEP_MILLISECONDS);
if (thread.isAlive()) {
// call the deprecated method as last possible exit
thread.stop();
throw new TimeExceeded();
}
}
if (fException != null) {
writer.write(fException.getMessage() != null ? fException.getMessage() : "Exception: " + fException.getClass().getName());
writer.write('\n');
}
if ((fEvaluationResult != null) && !fEvaluationResult.equals(F.Null)) {
OutputFormFactory.get(fRelaxedSyntax).convert(writer, fEvaluationResult);
}
return fEvaluationResult;
} catch (final Exception e) {
throw e;
}
}
/**
* Get the parsed expression after calling the constrainedEval()
* method
*
* @return the parsed expression; may return null
*/
public IExpr getParsedExpression() {
return fParsedExpression;
}
}
Ads help maintain this website.