Skip to content

Commit 0982186

Browse files
committed
Use a Job as the Reconciler Thread
Currently AbstractReconciler uses a raw thread for reconciling requests this has some pitfalls: 1) There is no way for the user to see this job even if it hangs for a long time 2) If the job framework is suspended (e.g during init of the IDE) some code is still executed because the reconciler is called from the creation of the text viewer This now replaces the bare thread with a job but retain current behaviour / API
1 parent 22ec1e2 commit 0982186

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

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

Lines changed: 39 additions & 20 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+
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,8 @@ public synchronized boolean isDirty() {
98105
/**
99106
* Cancels the background thread.
100107
*/
101-
public void cancel() {
108+
@Override
109+
protected void canceling() {
102110
fCanceled= true;
103111
IProgressMonitor pm= fProgressMonitor;
104112
if (pm != null)
@@ -153,7 +161,9 @@ public void reset() {
153161
fDirtyRegionQueue.notifyAll();
154162
}
155163
}
156-
164+
synchronized (this) {
165+
started= false;
166+
}
157167
informNotFinished();
158168
reconcilerReset();
159169
}
@@ -167,12 +177,12 @@ public void reset() {
167177
* </p>
168178
*/
169179
@Override
170-
public void run() {
171-
180+
public IStatus run(IProgressMonitor monitor) {
181+
fIsAlive= true;
172182
delay();
173183

174184
if (fCanceled)
175-
return;
185+
return Status.CANCEL_STATUS;
176186

177187
initialProcess();
178188

@@ -217,6 +227,19 @@ public void run() {
217227

218228
fIsActive= false;
219229
}
230+
fIsAlive= false;
231+
return Status.OK_STATUS;
232+
}
233+
234+
public boolean isAlive() {
235+
return fIsAlive;
236+
}
237+
238+
public synchronized void start() {
239+
if (!started) {
240+
started= true;
241+
schedule();
242+
}
220243
}
221244
}
222245

@@ -233,7 +256,7 @@ public void documentAboutToBeChanged(DocumentEvent e) {
233256
public void documentChanged(DocumentEvent e) {
234257

235258
if (fThread.isActive() || !fThread.isDirty() && fThread.isAlive()) {
236-
if (!fIsAllowedToModifyDocument && Thread.currentThread() == fThread)
259+
if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread())
237260
throw new UnsupportedOperationException("The reconciler thread is not allowed to modify the document"); //$NON-NLS-1$
238261
aboutToBeReconciledInternal();
239262
}
@@ -449,7 +472,7 @@ public void install(ITextViewer textViewer) {
449472
synchronized (this) {
450473
if (fThread != null)
451474
return;
452-
fThread= new BackgroundThread(getClass().getName());
475+
fThread= new BackgroundThread(getClass().getName() + " reconciler thread"); //$NON-NLS-1$
453476
}
454477

455478
fDirtyRegionQueue= new DirtyRegionQueue();
@@ -614,14 +637,7 @@ protected synchronized void startReconciling() {
614637
return;
615638

616639
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-
}
640+
fThread.start();
625641
} else {
626642
fThread.reset();
627643
}
@@ -640,7 +656,10 @@ protected void reconcilerReset() {
640656
* @return <code>true</code> if running in this reconciler's background thread
641657
* @since 3.4
642658
*/
643-
protected boolean isRunningInReconcilerThread() {
644-
return Thread.currentThread() == fThread;
659+
protected synchronized boolean isRunningInReconcilerThread() {
660+
if (fThread == null) {
661+
return false;
662+
}
663+
return Job.getJobManager().currentJob() == fThread;
645664
}
646665
}

0 commit comments

Comments
 (0)