@@ -55,7 +55,7 @@ abstract public class AbstractReconciler implements IReconciler {
5555 /**
5656 * Background thread for the reconciling activity.
5757 */
58- class BackgroundThread extends Thread {
58+ class BackgroundWorker implements Runnable {
5959
6060 /** Has the reconciler been canceled. */
6161 private boolean fCanceled = false ;
@@ -68,16 +68,14 @@ class BackgroundThread extends Thread {
6868
6969 private boolean fStarted ;
7070
71- /**
72- * Creates a new background thread. The thread
73- * runs with minimal priority.
74- *
75- * @param name the thread's name
76- */
77- public BackgroundThread (String name ) {
78- super (name );
79- setPriority (Thread .MIN_PRIORITY );
80- setDaemon (true );
71+ private String fName ;
72+
73+ private boolean fIsAlive ;
74+
75+ private volatile Thread fThread ;
76+
77+ public BackgroundWorker (String name ) {
78+ fName = name ;
8179 }
8280
8381 /**
@@ -172,74 +170,79 @@ public void reset() {
172170 */
173171 @ Override
174172 public void run () {
173+ try {
174+ while (!fCanceled ) {
175175
176- delay ();
177-
178- if (fCanceled )
179- return ;
180-
181- initialProcess ();
182-
183- while (!fCanceled ) {
184-
185- delay ();
186-
187- if (fCanceled )
188- break ;
176+ delay ();
189177
190- if (!isDirty ()) {
191- waitFinish = false ; //signalWaitForFinish() was called but nothing todo
192- continue ;
193- }
178+ if (fCanceled )
179+ break ;
194180
195- synchronized (this ) {
196- if (fReset ) {
197- fReset = false ;
181+ if (!isDirty ()) {
182+ waitFinish = false ; //signalWaitForFinish() was called but nothing todo
198183 continue ;
199184 }
200- }
201185
202- DirtyRegion r = null ;
203- synchronized (fDirtyRegionQueue ) {
204- r = fDirtyRegionQueue .removeNextDirtyRegion ();
205- }
186+ synchronized (this ) {
187+ if (fReset ) {
188+ fReset = false ;
189+ continue ;
190+ }
191+ }
206192
207- fIsActive = true ;
193+ DirtyRegion r = null ;
194+ synchronized (fDirtyRegionQueue ) {
195+ r = fDirtyRegionQueue .removeNextDirtyRegion ();
196+ }
208197
209- fProgressMonitor . setCanceled ( false ) ;
198+ fIsActive = true ;
210199
211- process ( r );
200+ fProgressMonitor . setCanceled ( false );
212201
213- synchronized (fDirtyRegionQueue ) {
214- if (0 == fDirtyRegionQueue .getSize ()) {
215- synchronized (this ) {
216- fIsDirty = fProgressMonitor .isCanceled ();
202+ process (r );
203+
204+ synchronized (fDirtyRegionQueue ) {
205+ if (0 == fDirtyRegionQueue .getSize ()) {
206+ synchronized (this ) {
207+ fIsDirty = fProgressMonitor .isCanceled ();
208+ }
209+ fDirtyRegionQueue .notifyAll ();
217210 }
218- fDirtyRegionQueue .notifyAll ();
219211 }
212+ fIsActive = false ;
220213 }
221-
222- fIsActive = false ;
214+ } finally {
215+ fIsAlive = false ;
223216 }
224217 }
225218
219+ boolean isAlive () {
220+ return fIsAlive ;
221+ }
222+
226223 public void startReconciling () {
227- if (!isAlive ()) {
228- if (fStarted ) {
229- return ;
230- }
224+ if (fStarted ) {
225+ fIsAlive = true ;
231226 fStarted = true ;
232227 Job .createSystem ("Delayed Reconciler startup" , m -> { //$NON-NLS-1$
233- try {
234- start ();
235- return Status . OK_STATUS ;
236- } catch ( IllegalThreadStateException e ) {
237- // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40549
238- // This is the only instance where the thread is started; since
239- // we checked that it is not alive, it must be dead already due
240- // to a run-time exception or error. Exit.
228+ //Until we process some code from the job, the reconciler thread is the current thread
229+ fThread = Thread . currentThread ();
230+ delay () ;
231+ if ( fCanceled ) {
232+ return Status . CANCEL_STATUS ;
233+ }
234+ initialProcess ();
235+ if ( fCanceled ) {
241236 return Status .CANCEL_STATUS ;
242237 }
238+ Thread thread = new Thread (this );
239+ thread .setName (fName );
240+ thread .setPriority (Thread .MIN_PRIORITY );
241+ thread .setDaemon (true );
242+ //we will no longer process any code here, so hand over to the worker thread.
243+ fThread = thread ;
244+ thread .start ();
245+ return Status .OK_STATUS ;
243246 }).schedule ();
244247 } else {
245248 reset ();
@@ -260,8 +263,8 @@ public void documentAboutToBeChanged(DocumentEvent e) {
260263 @ Override
261264 public void documentChanged (DocumentEvent e ) {
262265
263- if (fThread .isActive () || !fThread .isDirty () && fThread .isAlive ()) {
264- if (!fIsAllowedToModifyDocument && Thread . currentThread () == fThread )
266+ if (fWorker .isActive () || !fWorker .isDirty () && fWorker .isAlive ()) {
267+ if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread () )
265268 throw new UnsupportedOperationException ("The reconciler thread is not allowed to modify the document" ); //$NON-NLS-1$
266269 aboutToBeReconciledInternal ();
267270 }
@@ -270,13 +273,13 @@ public void documentChanged(DocumentEvent e) {
270273 * The second OR condition handles the case when the document
271274 * gets changed while still inside initialProcess().
272275 */
273- if (fThread .isActive () || fThread .isDirty () && fThread .isAlive ())
276+ if (fWorker .isActive () || fWorker .isDirty () && fWorker .isAlive ())
274277 fProgressMonitor .setCanceled (true );
275278
276279 if (fIsIncrementalReconciler )
277280 createDirtyRegion (e );
278281
279- fThread .reset ();
282+ fWorker .reset ();
280283
281284 }
282285
@@ -292,11 +295,11 @@ public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput
292295 synchronized (fDirtyRegionQueue ) {
293296 fDirtyRegionQueue .purgeQueue ();
294297 }
295- if (fDocument != null && fDocument .getLength () > 0 && fThread .isDirty () && fThread .isAlive ()) {
298+ if (fDocument != null && fDocument .getLength () > 0 && fWorker .isDirty () && fWorker .isAlive ()) {
296299 DocumentEvent e = new DocumentEvent (fDocument , 0 , fDocument .getLength (), "" ); //$NON-NLS-1$
297300 createDirtyRegion (e );
298- fThread .reset ();
299- fThread .suspendCallerWhileDirty ();
301+ fWorker .reset ();
302+ fWorker .suspendCallerWhileDirty ();
300303 }
301304 }
302305
@@ -316,7 +319,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
316319
317320 fDocument .addDocumentListener (this );
318321
319- if (!fThread .isDirty ())
322+ if (!fWorker .isDirty ())
320323 aboutToBeReconciledInternal ();
321324
322325 startReconciling ();
@@ -326,7 +329,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
326329 /** Queue to manage the changes applied to the text viewer. */
327330 private DirtyRegionQueue fDirtyRegionQueue ;
328331 /** The background thread. */
329- private BackgroundThread fThread ;
332+ private BackgroundWorker fWorker ;
330333 /** Internal document and text input listener. */
331334 private Listener fListener ;
332335 /** The background thread delay. */
@@ -475,9 +478,9 @@ public void install(ITextViewer textViewer) {
475478 fViewer = textViewer ;
476479
477480 synchronized (this ) {
478- if (fThread != null )
481+ if (fWorker != null )
479482 return ;
480- fThread = new BackgroundThread (getClass ().getName ());
483+ fWorker = new BackgroundWorker (getClass ().getName ());
481484 }
482485
483486 fDirtyRegionQueue = new DirtyRegionQueue ();
@@ -511,8 +514,8 @@ public void uninstall() {
511514
512515 synchronized (this ) {
513516 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
514- BackgroundThread bt = fThread ;
515- fThread = null ;
517+ BackgroundWorker bt = fWorker ;
518+ fWorker = null ;
516519 bt .cancel ();
517520 }
518521 }
@@ -618,10 +621,10 @@ protected void forceReconciling() {
618621
619622 if (fDocument != null ) {
620623
621- if (!fThread .isDirty ()&& fThread .isAlive ())
624+ if (!fWorker .isDirty ()&& fWorker .isAlive ())
622625 aboutToBeReconciledInternal ();
623626
624- if (fThread .isActive ())
627+ if (fWorker .isActive ())
625628 fProgressMonitor .setCanceled (true );
626629
627630 if (fIsIncrementalReconciler ) {
@@ -638,10 +641,10 @@ protected void forceReconciling() {
638641 * Clients may extend this method.
639642 */
640643 protected synchronized void startReconciling () {
641- if (fThread == null )
644+ if (fWorker == null )
642645 return ;
643646
644- fThread .startReconciling ();
647+ fWorker .startReconciling ();
645648 }
646649
647650 /**
@@ -657,7 +660,9 @@ protected void reconcilerReset() {
657660 * @return <code>true</code> if running in this reconciler's background thread
658661 * @since 3.4
659662 */
660- protected boolean isRunningInReconcilerThread () {
661- return Thread .currentThread () == fThread ;
663+ protected synchronized boolean isRunningInReconcilerThread () {
664+ if (fWorker == null )
665+ return false ;
666+ return Thread .currentThread () == fWorker .fThread ;
662667 }
663668}
0 commit comments