mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-01 02:46:41 +00:00
Add better control over expression timeouts. (#451)
Add better control over expression timeouts. * //timeout command can be used to change player's current timeout. * Config now also has a max timeout, can be bypassed with permission * Timeout of < 0 will let expressions run indefinitely. * Said expressions won't run on a separate thread, slightly reducing the overhead from context switching. For large //gen commands, for example, this can actually increase speed.
This commit is contained in:
@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.expression.parser.Parser;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Constant;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ExpressionTimeoutException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.Functions;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.RValue;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.ReturnException;
|
||||
@ -36,7 +37,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -117,6 +117,10 @@ public class Expression {
|
||||
}
|
||||
|
||||
public double evaluate(double... values) throws EvaluationException {
|
||||
return evaluate(values, WorldEdit.getInstance().getConfiguration().calculationTimeout);
|
||||
}
|
||||
|
||||
public double evaluate(double[] values, int timeout) throws EvaluationException {
|
||||
for (int i = 0; i < values.length; ++i) {
|
||||
final String variableName = variableNames[i];
|
||||
final RValue invokable = variables.get(variableName);
|
||||
@ -127,34 +131,44 @@ public class Expression {
|
||||
((Variable) invokable).value = values[i];
|
||||
}
|
||||
|
||||
Future<Double> result = evalThread.submit(new Callable<Double>() {
|
||||
@Override
|
||||
public Double call() throws Exception {
|
||||
pushInstance();
|
||||
try {
|
||||
return root.getValue();
|
||||
} finally {
|
||||
popInstance();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
return result.get(WorldEdit.getInstance().getConfiguration().calculationTimeout, TimeUnit.MILLISECONDS);
|
||||
if (timeout < 0) {
|
||||
return evaluateRoot();
|
||||
}
|
||||
return evaluateRootTimed(timeout);
|
||||
} catch (ReturnException e) {
|
||||
return e.getValue();
|
||||
} // other evaluation exceptions are thrown out of this method
|
||||
}
|
||||
|
||||
private double evaluateRootTimed(int timeout) throws EvaluationException {
|
||||
Future<Double> result = evalThread.submit(this::evaluateRoot);
|
||||
try {
|
||||
return result.get(timeout, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
} catch (TimeoutException e) {
|
||||
result.cancel(true);
|
||||
throw new ExpressionTimeoutException("Calculations exceeded time limit.");
|
||||
} catch (ExecutionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof ReturnException) {
|
||||
return ((ReturnException) cause).getValue();
|
||||
if (cause instanceof EvaluationException) {
|
||||
throw (EvaluationException) cause;
|
||||
}
|
||||
if (cause instanceof RuntimeException) {
|
||||
throw (RuntimeException) cause;
|
||||
}
|
||||
throw new RuntimeException(cause);
|
||||
} catch (TimeoutException e) {
|
||||
result.cancel(true);
|
||||
throw new EvaluationException(-1, "Calculations exceeded time limit.");
|
||||
}
|
||||
}
|
||||
|
||||
private Double evaluateRoot() throws EvaluationException {
|
||||
pushInstance();
|
||||
try {
|
||||
return root.getValue();
|
||||
} finally {
|
||||
popInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.internal.expression.runtime;
|
||||
|
||||
/**
|
||||
* Thrown when an evaluation exceeds the timeout time.
|
||||
*/
|
||||
public class ExpressionTimeoutException extends EvaluationException {
|
||||
public ExpressionTimeoutException(String message) {
|
||||
super(-1, message);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user