summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Joe2025-09-10 14:40:06 +0100
committerGravatar modmuss2025-09-13 09:14:23 +0100
commita391f202f5cccfeaa55ed30cd43f1b2a697aeb73 (patch)
tree9328d121a1732062a871b255d1559eb39331b9b5
parentAdd a way for plugins to invalidate data (mappings, javadocs, decompile), and... (diff)
downloadenigma-a391f202f5cccfeaa55ed30cd43f1b2a697aeb73.tar.gz
enigma-a391f202f5cccfeaa55ed30cd43f1b2a697aeb73.tar.xz
enigma-a391f202f5cccfeaa55ed30cd43f1b2a697aeb73.zip
Fix threading issues in ClassHandleProvider that are likely to come up if a plugin frequently invalidates class handles
-rw-r--r--enigma-swing/src/main/java/cuchaz/enigma/gui/panels/EditorPanel.java14
-rw-r--r--enigma/src/main/java/cuchaz/enigma/classhandle/ClassHandleProvider.java58
2 files changed, 55 insertions, 17 deletions
diff --git a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/EditorPanel.java b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/EditorPanel.java
index fb30f87a..6b341ee0 100644
--- a/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/EditorPanel.java
+++ b/enigma-swing/src/main/java/cuchaz/enigma/gui/panels/EditorPanel.java
@@ -333,15 +333,13 @@ public class EditorPanel {
333 } 333 }
334 334
335 private void handleDecompilerResult(Result<DecompiledClassSource, ClassHandleError> res) { 335 private void handleDecompilerResult(Result<DecompiledClassSource, ClassHandleError> res) {
336 SwingUtilities.invokeLater(() -> { 336 if (res.isOk()) {
337 if (res.isOk()) { 337 this.setSource(res.unwrap());
338 this.setSource(res.unwrap()); 338 } else {
339 } else { 339 this.displayError(res.unwrapErr());
340 this.displayError(res.unwrapErr()); 340 }
341 }
342 341
343 this.nextReference = null; 342 this.nextReference = null;
344 });
345 } 343 }
346 344
347 public void displayError(ClassHandleError t) { 345 public void displayError(ClassHandleError t) {
diff --git a/enigma/src/main/java/cuchaz/enigma/classhandle/ClassHandleProvider.java b/enigma/src/main/java/cuchaz/enigma/classhandle/ClassHandleProvider.java
index f441bf49..cb80dda9 100644
--- a/enigma/src/main/java/cuchaz/enigma/classhandle/ClassHandleProvider.java
+++ b/enigma/src/main/java/cuchaz/enigma/classhandle/ClassHandleProvider.java
@@ -18,6 +18,8 @@ import java.util.concurrent.atomic.AtomicInteger;
18import java.util.concurrent.locks.ReadWriteLock; 18import java.util.concurrent.locks.ReadWriteLock;
19import java.util.concurrent.locks.ReentrantReadWriteLock; 19import java.util.concurrent.locks.ReentrantReadWriteLock;
20 20
21import javax.swing.SwingUtilities;
22
21import org.jetbrains.annotations.Nullable; 23import org.jetbrains.annotations.Nullable;
22 24
23import cuchaz.enigma.EnigmaProject; 25import cuchaz.enigma.EnigmaProject;
@@ -230,6 +232,8 @@ public final class ClassHandleProvider {
230 private final AtomicInteger mappedVersion = new AtomicInteger(); 232 private final AtomicInteger mappedVersion = new AtomicInteger();
231 233
232 private final ReadWriteLock lock = new ReentrantReadWriteLock(); 234 private final ReadWriteLock lock = new ReentrantReadWriteLock();
235 private final Object decompileCompleteMutex = new Object();
236 private final Object mappedCompleteMutex = new Object();
233 237
234 private Entry(ClassHandleProvider p, ClassEntry entry) { 238 private Entry(ClassHandleProvider p, ClassEntry entry) {
235 this.p = p; 239 this.p = p;
@@ -287,10 +291,26 @@ public final class ClassHandleProvider {
287 } 291 }
288 292
289 Result<Source, ClassHandleError> uncommentedSource = Result.ok(p.decompiler.getSource(entry.getFullName())); 293 Result<Source, ClassHandleError> uncommentedSource = Result.ok(p.decompiler.getSource(entry.getFullName()));
290 Entry.this.uncommentedSource = uncommentedSource; 294
291 Entry.this.waitingUncommentedSources.forEach(f -> f.complete(uncommentedSource)); 295 synchronized (decompileCompleteMutex) {
292 Entry.this.waitingUncommentedSources.clear(); 296 if (decompileVersion.get() != v) {
293 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onUncommentedSourceChanged(uncommentedSource)); 297 return null;
298 }
299
300 Entry.this.uncommentedSource = uncommentedSource;
301
302 synchronized (Entry.this.waitingUncommentedSources) {
303 Entry.this.waitingUncommentedSources.forEach(f -> f.complete(uncommentedSource));
304 Entry.this.waitingUncommentedSources.clear();
305 }
306
307 SwingUtilities.invokeLater(() -> {
308 if (decompileVersion.get() == v) {
309 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onUncommentedSourceChanged(uncommentedSource));
310 }
311 });
312 }
313
294 return uncommentedSource; 314 return uncommentedSource;
295 }, p.pool); 315 }, p.pool);
296 } 316 }
@@ -303,7 +323,13 @@ public final class ClassHandleProvider {
303 } 323 }
304 324
305 Result<Source, ClassHandleError> jdSource = res.map(s -> s.withJavadocs(p.project.getMapper())); 325 Result<Source, ClassHandleError> jdSource = res.map(s -> s.withJavadocs(p.project.getMapper()));
306 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onDocsChanged(jdSource)); 326
327 SwingUtilities.invokeLater(() -> {
328 if (javadocVersion.get() == v) {
329 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onDocsChanged(jdSource));
330 }
331 });
332
307 return jdSource; 333 return jdSource;
308 }, p.pool); 334 }, p.pool);
309 } 335 }
@@ -341,10 +367,24 @@ public final class ClassHandleProvider {
341 return; 367 return;
342 } 368 }
343 369
344 Entry.this.source = res; 370 synchronized (mappedCompleteMutex) {
345 Entry.this.waitingSources.forEach(s -> s.complete(source)); 371 if (mappedVersion.get() != v) {
346 Entry.this.waitingSources.clear(); 372 return;
347 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onMappedSourceChanged(source)); 373 }
374
375 Entry.this.source = res;
376
377 synchronized (Entry.this.waitingSources) {
378 Entry.this.waitingSources.forEach(s -> s.complete(source));
379 Entry.this.waitingSources.clear();
380 }
381
382 SwingUtilities.invokeLater(() -> {
383 if (mappedVersion.get() == v) {
384 withLock(lock.readLock(), () -> new ArrayList<>(handles)).forEach(h -> h.onMappedSourceChanged(source));
385 }
386 });
387 }
348 }); 388 });
349 } 389 }
350 390