Skip to content

Commit

Permalink
Added "synchronized" keyword to these methods to avoid Concurrency mo…
Browse files Browse the repository at this point in the history
…dify data:

- EvalEngine#popOptionsStack
- EvalEngine#peekOptionsStack
- EvalEngine#pushOptionsStack
- EvalEngine#stackBegin
- EvalEngine#stackPop
- Context#computeIfAbsent
- Symbol#evalDownRule

see ConcurrencyTest.java
  • Loading branch information
duytranle committed Sep 14, 2023
1 parent 43f9254 commit ae6a746
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2784,7 +2784,7 @@ public EvalHistory getEvalHistory() {
return fEvalHistory;
}

public OptionsStack pushOptionsStack() {
public synchronized OptionsStack pushOptionsStack() {
fOptionsStack.push();
return fOptionsStack;
}
Expand All @@ -2811,11 +2811,11 @@ public void putObjectCache(IExpr key, Object value) {
globalObjectCache.put(key, value);
}

public void popOptionsStack() {
public synchronized void popOptionsStack() {
fOptionsStack.pop();
}

public IdentityHashMap<ISymbol, IASTAppendable> peekOptionsStack() {
public synchronized IdentityHashMap<ISymbol, IASTAppendable> peekOptionsStack() {
return fOptionsStack.peek();
}

Expand Down Expand Up @@ -2990,16 +2990,16 @@ public final void init() {
rememberMap = new IdentityHashMap<Object, IExpr>();
}

public Deque<IExpr> stackBegin() {
public synchronized Deque<IExpr> stackBegin() {
fStack = new ArrayDeque<IExpr>(256);
return fStack;
}

public void stackPush(IExpr expr) {
public synchronized void stackPush(IExpr expr) {
fStack.push(expr);
}

public IExpr stackPop() {
public synchronized IExpr stackPop() {
if (fStack.isEmpty()) {
return F.NIL;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.matheclipse.core.basic.Config;
import org.matheclipse.core.builtin.JavaFunctions;
Expand Down Expand Up @@ -144,15 +145,15 @@ public ISymbol put(String key, ISymbol value) {
return symbolTable.put(key, value);
}

public ISymbol computeIfAbsent(String key, Function<String, ISymbol> mappingFunction) {
public synchronized ISymbol computeIfAbsent(String key, Function<String, ISymbol> mappingFunction) {
return symbolTable.computeIfAbsent(key, mappingFunction);
}

private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
contextName = stream.readUTF();
int size = stream.readInt();
symbolTable = new HashMap<>(size + size / 10);
symbolTable = new ConcurrentHashMap<>(size + size / 10);
EvalEngine.get().getContextPath().setGlobalContext(this);
String[] table = new String[size];
for (int i = 0; i < size; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ public boolean equals(Object obj) {

/** {@inheritDoc} */
@Override
public final IExpr evalDownRule(EvalEngine engine, IExpr expression) {
public final synchronized IExpr evalDownRule(EvalEngine engine, IExpr expression) {
if (fRulesData == null) {
return F.NIL;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.matheclipse.core.system;

import org.junit.Test;
import org.matheclipse.core.eval.ExprEvaluator;
import org.matheclipse.core.interfaces.IExpr;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ConcurrencyTest {

@Test
public void test001() throws InterruptedException, ExecutionException {

String str = "SinDegree(x_):=Sin(x*Pi/180)";

ExprEvaluator exprEvaluator = new ExprEvaluator();

ExecutorService threadPool = Executors.newFixedThreadPool(4);
List<Callable<IExpr>> tasks = new ArrayList<>();
for (int i = 0; i < 20; i++) {
tasks.add(() -> {
exprEvaluator.eval(str);
return exprEvaluator.eval("Definition[SinDegree]");
});
tasks.add(() -> exprEvaluator.eval("Int[Sin(x) * Cos(x) , x]"));
}


List<Future<IExpr>> futures = threadPool.invokeAll(tasks);
threadPool.shutdown();

for (Future<IExpr> future : futures) {
IExpr iExpr = future.get();
//System.out.println("iExpr = " + iExpr);
}

}

}

0 comments on commit ae6a746

Please sign in to comment.