From 7f32329ce13a1d5a36c68d7464cff0b9f06de90d Mon Sep 17 00:00:00 2001
From: Ed Merks
Date: Fri, 6 Jun 2025 14:48:43 +0200
Subject: [PATCH 1/2] Use a Job as the Reconciler Thread for AbstractReconciler
Currently AbstractReconciler uses a raw thread for reconciling requests.
This has the problem that if the job framework is suspended (e.g, during
startup of the IDE) some code is still executed because the reconciler
is called from the creation of the text viewer and starts immediately.
This replaces the bare thread with a job but retains current
behaviour. Note that the job cannot be manually terminated, just as the
thread continued to run indefinitely until explicitly terminated.
https://github.com/eclipse-platform/eclipse.platform.ui/pull/3018
---
.../text/reconciler/AbstractReconciler.java | 65 +++++++++++++------
1 file changed, 44 insertions(+), 21 deletions(-)
diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java
index c7dccfda290..3895aed0df5 100644
--- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java
+++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java
@@ -15,7 +15,10 @@
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
@@ -53,7 +56,7 @@ abstract public class AbstractReconciler implements IReconciler {
/**
* Background thread for the reconciling activity.
*/
- class BackgroundThread extends Thread {
+ private class BackgroundThread extends Job {
/** Has the reconciler been canceled. */
private boolean fCanceled= false;
@@ -64,6 +67,10 @@ class BackgroundThread extends Thread {
/** Is a reconciling strategy active. */
private boolean fIsActive= false;
+ private volatile boolean fIsAlive;
+
+ private boolean started;
+
/**
* Creates a new background thread. The thread
* runs with minimal priority.
@@ -72,8 +79,8 @@ class BackgroundThread extends Thread {
*/
public BackgroundThread(String name) {
super(name);
- setPriority(Thread.MIN_PRIORITY);
- setDaemon(true);
+ setPriority(Job.DECORATE);
+ setSystem(true);
}
/**
@@ -98,7 +105,7 @@ public synchronized boolean isDirty() {
/**
* Cancels the background thread.
*/
- public void cancel() {
+ public void doCancel() {
fCanceled= true;
IProgressMonitor pm= fProgressMonitor;
if (pm != null)
@@ -153,7 +160,9 @@ public void reset() {
fDirtyRegionQueue.notifyAll();
}
}
-
+ synchronized (this) {
+ started= false;
+ }
informNotFinished();
reconcilerReset();
}
@@ -167,12 +176,12 @@ public void reset() {
*
*/
@Override
- public void run() {
-
+ public IStatus run(IProgressMonitor monitor) {
+ fIsAlive= true;
delay();
if (fCanceled)
- return;
+ return Status.CANCEL_STATUS;
initialProcess();
@@ -217,6 +226,24 @@ public void run() {
fIsActive= false;
}
+ fIsAlive= false;
+ return Status.OK_STATUS;
+ }
+
+ public boolean isAlive() {
+ return fIsAlive;
+ }
+
+ public synchronized void start() {
+ if (!started) {
+ started= true;
+ schedule();
+ }
+ }
+
+ @Override
+ public boolean belongsTo(Object family) {
+ return family == fViewer || AbstractReconciler.class == family;
}
}
@@ -233,7 +260,7 @@ public void documentAboutToBeChanged(DocumentEvent e) {
public void documentChanged(DocumentEvent e) {
if (fThread.isActive() || !fThread.isDirty() && fThread.isAlive()) {
- if (!fIsAllowedToModifyDocument && Thread.currentThread() == fThread)
+ if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread())
throw new UnsupportedOperationException("The reconciler thread is not allowed to modify the document"); //$NON-NLS-1$
aboutToBeReconciledInternal();
}
@@ -485,7 +512,7 @@ public void uninstall() {
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
BackgroundThread bt= fThread;
fThread= null;
- bt.cancel();
+ bt.doCancel();
}
}
}
@@ -614,14 +641,7 @@ protected synchronized void startReconciling() {
return;
if (!fThread.isAlive()) {
- try {
- fThread.start();
- } catch (IllegalThreadStateException e) {
- // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40549
- // This is the only instance where the thread is started; since
- // we checked that it is not alive, it must be dead already due
- // to a run-time exception or error. Exit.
- }
+ fThread.start();
} else {
fThread.reset();
}
@@ -640,7 +660,10 @@ protected void reconcilerReset() {
* @return true if running in this reconciler's background thread
* @since 3.4
*/
- protected boolean isRunningInReconcilerThread() {
- return Thread.currentThread() == fThread;
+ protected synchronized boolean isRunningInReconcilerThread() {
+ if (fThread == null) {
+ return false;
+ }
+ return Job.getJobManager().currentJob() == fThread;
}
-}
+}
\ No newline at end of file
From 03da687cc13db1504da249f9da9e94eedbbceccd Mon Sep 17 00:00:00 2001
From: Eclipse Platform Bot
Date: Fri, 6 Jun 2025 12:53:36 +0000
Subject: [PATCH 2/2] Version bump(s) for 4.37 stream
---
bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
index d1429ea7467..a5507fd35c1 100644
--- a/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.jface.text/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.jface.text
-Bundle-Version: 3.28.0.qualifier
+Bundle-Version: 3.28.100.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: