Skip to content

Commit 7398764

Browse files
committed
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. #3018
1 parent 7429002 commit 7398764

File tree

1 file changed

+44
-21
lines changed

1 file changed

+44
-21
lines changed

bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515

1616
import org.eclipse.core.runtime.Assert;
1717
import org.eclipse.core.runtime.IProgressMonitor;
18+
import org.eclipse.core.runtime.IStatus;
1819
import org.eclipse.core.runtime.NullProgressMonitor;
20+
import org.eclipse.core.runtime.Status;
21+
import org.eclipse.core.runtime.jobs.Job;
1922

2023
import org.eclipse.jface.text.DocumentEvent;
2124
import org.eclipse.jface.text.IDocument;
@@ -53,7 +56,7 @@ abstract public class AbstractReconciler implements IReconciler {
5356
/**
5457
* Background thread for the reconciling activity.
5558
*/
56-
class BackgroundThread extends Thread {
59+
private class BackgroundThread extends Job {
5760

5861
/** Has the reconciler been canceled. */
5962
private boolean fCanceled= false;
@@ -64,6 +67,10 @@ class BackgroundThread extends Thread {
6467
/** Is a reconciling strategy active. */
6568
private boolean fIsActive= false;
6669

70+
private volatile boolean fIsAlive;
71+
72+
private boolean started;
73+
6774
/**
6875
* Creates a new background thread. The thread
6976
* runs with minimal priority.
@@ -72,8 +79,8 @@ class BackgroundThread extends Thread {
7279
*/
7380
public BackgroundThread(String name) {
7481
super(name);
75-
setPriority(Thread.MIN_PRIORITY);
76-
setDaemon(true);
82+
setPriority(Job.DECORATE);
83+
setSystem(true);
7784
}
7885

7986
/**
@@ -98,7 +105,7 @@ public synchronized boolean isDirty() {
98105
/**
99106
* Cancels the background thread.
100107
*/
101-
public void cancel() {
108+
public void doCancel() {
102109
fCanceled= true;
103110
IProgressMonitor pm= fProgressMonitor;
104111
if (pm != null)
@@ -153,7 +160,9 @@ public void reset() {
153160
fDirtyRegionQueue.notifyAll();
154161
}
155162
}
156-
163+
synchronized (this) {
164+
started= false;
165+
}
157166
informNotFinished();
158167
reconcilerReset();
159168
}
@@ -167,12 +176,12 @@ public void reset() {
167176
* </p>
168177
*/
169178
@Override
170-
public void run() {
171-
179+
public IStatus run(IProgressMonitor monitor) {
180+
fIsAlive= true;
172181
delay();
173182

174183
if (fCanceled)
175-
return;
184+
return Status.CANCEL_STATUS;
176185

177186
initialProcess();
178187

@@ -217,6 +226,24 @@ public void run() {
217226

218227
fIsActive= false;
219228
}
229+
fIsAlive= false;
230+
return Status.OK_STATUS;
231+
}
232+
233+
public boolean isAlive() {
234+
return fIsAlive;
235+
}
236+
237+
public synchronized void start() {
238+
if (!started) {
239+
started= true;
240+
schedule();
241+
}
242+
}
243+
244+
@Override
245+
public boolean belongsTo(Object family) {
246+
return family == fViewer || AbstractReconciler.class == family;
220247
}
221248
}
222249

@@ -233,7 +260,7 @@ public void documentAboutToBeChanged(DocumentEvent e) {
233260
public void documentChanged(DocumentEvent e) {
234261

235262
if (fThread.isActive() || !fThread.isDirty() && fThread.isAlive()) {
236-
if (!fIsAllowedToModifyDocument && Thread.currentThread() == fThread)
263+
if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread())
237264
throw new UnsupportedOperationException("The reconciler thread is not allowed to modify the document"); //$NON-NLS-1$
238265
aboutToBeReconciledInternal();
239266
}
@@ -485,7 +512,7 @@ public void uninstall() {
485512
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
486513
BackgroundThread bt= fThread;
487514
fThread= null;
488-
bt.cancel();
515+
bt.doCancel();
489516
}
490517
}
491518
}
@@ -614,14 +641,7 @@ protected synchronized void startReconciling() {
614641
return;
615642

616643
if (!fThread.isAlive()) {
617-
try {
618-
fThread.start();
619-
} catch (IllegalThreadStateException e) {
620-
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40549
621-
// This is the only instance where the thread is started; since
622-
// we checked that it is not alive, it must be dead already due
623-
// to a run-time exception or error. Exit.
624-
}
644+
fThread.start();
625645
} else {
626646
fThread.reset();
627647
}
@@ -640,7 +660,10 @@ protected void reconcilerReset() {
640660
* @return <code>true</code> if running in this reconciler's background thread
641661
* @since 3.4
642662
*/
643-
protected boolean isRunningInReconcilerThread() {
644-
return Thread.currentThread() == fThread;
663+
protected synchronized boolean isRunningInReconcilerThread() {
664+
if (fThread == null) {
665+
return false;
666+
}
667+
return Job.getJobManager().currentJob() == fThread;
645668
}
646-
}
669+
}

0 commit comments

Comments
 (0)