Allow parallelisation of masks (#636)

* Allow parallelisation of masks
Increasing performance improvement with increased masking complexity and edit size.

* Address comments
 - Rename Mask#clone to Mask#copy
 - Rename Mask2D#copy to Mask2D#copy2D
 - Correct formatting

* cx -> centerX

* Make various operations relying on a single SingleThreadQueueExtent instance (mainly brushes) thread safe
This commit is contained in:
dordsor21
2020-09-25 15:00:42 +01:00
committed by GitHub
parent 3f1e8fa4d4
commit 855389c785
70 changed files with 893 additions and 266 deletions

View File

@ -31,8 +31,10 @@ import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import java.time.Instant;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* Compiles and evaluates expressions.
@ -60,19 +62,55 @@ import java.util.Objects;
* pass values for all slots specified while compiling.
* To query slots after evaluation, you can use the {@linkplain #getSlots() slot table}.
*/
public class Expression {
public class Expression implements Cloneable {
private final SlotTable slots = new SlotTable();
private final List<String> providedSlots;
private final ExpressionParser.AllStatementsContext root;
private final Functions functions = Functions.create();
private final CompiledExpression compiledExpression;
private final String initialExpression;
public static Expression compile(String expression, String... variableNames) throws ExpressionException {
return new Expression(expression, variableNames);
}
private Expression(String expression, String... variableNames) throws ExpressionException {
this.initialExpression = expression;
slots.putSlot("e", new LocalSlot.Constant(Math.E));
slots.putSlot("pi", new LocalSlot.Constant(Math.PI));
slots.putSlot("true", new LocalSlot.Constant(1));
slots.putSlot("false", new LocalSlot.Constant(0));
for (String variableName : variableNames) {
slots.initVariable(variableName)
.orElseThrow(() -> new ExpressionException(-1,
"Tried to overwrite identifier '" + variableName + "'"));
}
this.providedSlots = ImmutableList.copyOf(variableNames);
CharStream cs = CharStreams.fromString(expression, "<input>");
ExpressionLexer lexer = new ExpressionLexer(cs);
lexer.removeErrorListeners();
lexer.addErrorListener(new LexerErrorListener());
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExpressionParser parser = new ExpressionParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(new ParserErrorListener());
try {
root = parser.allStatements();
Objects.requireNonNull(root, "Unable to parse root, but no exceptions?");
} catch (ParseCancellationException e) {
throw new ParserException(parser.getState(), e);
}
ParseTreeWalker.DEFAULT.walk(new ExpressionValidator(slots.keySet(), functions), root);
this.compiledExpression = new ExpressionCompiler().compileExpression(root, functions);
}
private Expression(String expression, Set<String> variableNames) throws ExpressionException {
this.initialExpression = expression;
slots.putSlot("e", new LocalSlot.Constant(Math.E));
slots.putSlot("pi", new LocalSlot.Constant(Math.PI));
slots.putSlot("true", new LocalSlot.Constant(1));
@ -147,4 +185,8 @@ public class Expression {
functions.setEnvironment(environment);
}
public Expression clone() {
return new Expression(initialExpression, new HashSet<>(providedSlots));
}
}