Skip to content

Commit 8f12db2

Browse files
committed
fix: race conditions when using the same grammar concurrently
1 parent 075d8b6 commit 8f12db2

File tree

2 files changed

+38
-5
lines changed
  • org.eclipse.tm4e.core/src

2 files changed

+38
-5
lines changed

org.eclipse.tm4e.core/src/main/java/org/eclipse/tm4e/core/internal/grammar/Grammar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ public ITokenizeLineResult<int[]> tokenizeLine2(final String lineText, final @Nu
267267
}
268268

269269
@SuppressWarnings("unchecked")
270-
private <T> T _tokenize(
270+
private synchronized <T> T _tokenize(
271271
String lineText,
272272
@Nullable StateStack prevState,
273273
final boolean emitBinaryTokens,

org.eclipse.tm4e.core/src/test/java/org/eclipse/tm4e/core/grammar/GrammarTest.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,21 @@
1515
import static org.junit.jupiter.api.Assertions.*;
1616

1717
import java.io.IOException;
18+
import java.nio.file.Files;
19+
import java.nio.file.Paths;
1820
import java.time.Duration;
21+
import java.util.ArrayList;
1922
import java.util.Arrays;
2023
import java.util.List;
24+
import java.util.concurrent.Executors;
25+
import java.util.concurrent.Future;
26+
import java.util.concurrent.TimeUnit;
2127
import java.util.stream.Collectors;
2228

2329
import org.eclipse.tm4e.core.Data;
2430
import org.eclipse.tm4e.core.internal.utils.ResourceUtils;
2531
import org.eclipse.tm4e.core.registry.IGrammarSource;
2632
import org.eclipse.tm4e.core.registry.Registry;
27-
import org.junit.jupiter.api.Assertions;
2833
import org.junit.jupiter.api.Disabled;
2934
import org.junit.jupiter.api.MethodOrderer;
3035
import org.junit.jupiter.api.Test;
@@ -71,6 +76,34 @@ class GrammarTest {
7176
"Token from 11 to 14 with scopes [source.js, meta.function.js, meta.decl.block.js]",
7277
"Token from 14 to 15 with scopes [source.js, meta.function.js, meta.decl.block.js, meta.brace.curly.js]" };
7378

79+
@Test
80+
void testTokenizeConcurrent() throws Exception {
81+
final var registry = new Registry();
82+
final var grammar = registry.addGrammar(fromFile(Paths.get("../org.eclipse.tm4e.language_pack/syntaxes/xml/xml.tmLanguage.json")));
83+
final String content = Files.readString(Paths.get("../org.eclipse.tm4e.language_pack/syntaxes/xml/xml.example.xml"));
84+
85+
final int numThreads = 4;
86+
final var executor = Executors.newFixedThreadPool(numThreads);
87+
final Runnable tokenizationTask = () -> {
88+
for (int i = 0; i < 2; i++) {
89+
final var r = TokenizationUtils.tokenizeText(content, grammar);
90+
assertTrue(r.count() > 1);
91+
}
92+
};
93+
94+
final List<Future<?>> futures = new ArrayList<>();
95+
for (int i = 0; i < numThreads; i++) {
96+
futures.add(executor.submit(tokenizationTask));
97+
}
98+
99+
for (final Future<?> future : futures) {
100+
future.get();
101+
}
102+
103+
executor.shutdown();
104+
executor.awaitTermination(1, TimeUnit.MINUTES);
105+
}
106+
74107
@Test
75108
void testTokenizeSingleLineExpression() throws Exception {
76109
final var registry = new Registry();
@@ -80,7 +113,7 @@ void testTokenizeSingleLineExpression() throws Exception {
80113
for (int i = 0; i < lineTokens.getTokens().length; i++) {
81114
final IToken token = lineTokens.getTokens()[i];
82115
final String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + token.getScopes();
83-
Assertions.assertEquals(EXPECTED_SINGLE_LINE_TOKENS[i], s);
116+
assertEquals(EXPECTED_SINGLE_LINE_TOKENS[i], s);
84117
}
85118
}
86119

@@ -100,7 +133,7 @@ void testTokenizeMultilineExpression() throws Exception {
100133
for (i = 0; i < lineTokens.getTokens().length; i++) {
101134
final IToken token = lineTokens.getTokens()[i];
102135
final String s = "Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + token.getScopes();
103-
Assertions.assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s);
136+
assertEquals(EXPECTED_MULTI_LINE_TOKENS[i + j], s);
104137
}
105138
j = i;
106139
}
@@ -220,7 +253,7 @@ void testTokenizeTypeScriptFile() throws Exception {
220253
for (int i = 0; i < lineTokens.getTokens().length; i++) {
221254
tokenIndex++;
222255
final var token = lineTokens.getTokens()[i];
223-
Assertions.assertEquals(
256+
assertEquals(
224257
expectedTokens.get(tokenIndex),
225258
"Token from " + token.getStartIndex() + " to " + token.getEndIndex() + " with scopes " + token.getScopes());
226259
}

0 commit comments

Comments
 (0)