Skip to content

Commit 9d0047b

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 9d0047b

File tree

1 file changed

+36
-19
lines changed

1 file changed

+36
-19
lines changed

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

Lines changed: 36 additions & 19 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 Thread myThread;
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)
@@ -167,12 +175,12 @@ public void reset() {
167175
* </p>
168176
*/
169177
@Override
170-
public void run() {
171-
178+
public IStatus run(IProgressMonitor monitor) {
179+
myThread= Thread.currentThread();
172180
delay();
173181

174182
if (fCanceled)
175-
return;
183+
return Status.CANCEL_STATUS;
176184

177185
initialProcess();
178186

@@ -217,6 +225,19 @@ public void run() {
217225

218226
fIsActive= false;
219227
}
228+
myThread= null;
229+
return Status.OK_STATUS;
230+
}
231+
232+
public boolean isAlive() {
233+
return myThread != null;
234+
}
235+
236+
public synchronized void start() {
237+
if (!started) {
238+
started= true;
239+
schedule();
240+
}
220241
}
221242
}
222243

@@ -233,7 +254,7 @@ public void documentAboutToBeChanged(DocumentEvent e) {
233254
public void documentChanged(DocumentEvent e) {
234255

235256
if (fThread.isActive() || !fThread.isDirty() && fThread.isAlive()) {
236-
if (!fIsAllowedToModifyDocument && Thread.currentThread() == fThread)
257+
if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread())
237258
throw new UnsupportedOperationException("The reconciler thread is not allowed to modify the document"); //$NON-NLS-1$
238259
aboutToBeReconciledInternal();
239260
}
@@ -449,7 +470,7 @@ public void install(ITextViewer textViewer) {
449470
synchronized (this) {
450471
if (fThread != null)
451472
return;
452-
fThread= new BackgroundThread(getClass().getName());
473+
fThread= new BackgroundThread(getClass().getName() + " reconciler thread"); //$NON-NLS-1$
453474
}
454475

455476
fDirtyRegionQueue= new DirtyRegionQueue();
@@ -614,14 +635,7 @@ protected synchronized void startReconciling() {
614635
return;
615636

616637
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-
}
638+
fThread.start();
625639
} else {
626640
fThread.reset();
627641
}
@@ -640,7 +654,10 @@ protected void reconcilerReset() {
640654
* @return <code>true</code> if running in this reconciler's background thread
641655
* @since 3.4
642656
*/
643-
protected boolean isRunningInReconcilerThread() {
644-
return Thread.currentThread() == fThread;
657+
protected synchronized boolean isRunningInReconcilerThread() {
658+
if (fThread == null) {
659+
return false;
660+
}
661+
return Thread.currentThread() == fThread.myThread;
645662
}
646663
}

0 commit comments

Comments
 (0)