@@ -55,29 +55,27 @@ 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. */
61- private boolean fCanceled = false ;
61+ private boolean fCanceled ;
6262 /** Has the reconciler been reset. */
63- private boolean fReset = false ;
63+ private boolean fReset ;
6464 /** Some changes need to be processed. */
65- private boolean fIsDirty = false ;
65+ private boolean fIsDirty ;
6666 /** Is a reconciling strategy active. */
67- private boolean fIsActive = false ;
67+ private boolean fIsActive ;
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 /**
@@ -166,80 +164,86 @@ public void reset() {
166164 * The background activity. Waits until there is something in the
167165 * queue managing the changes that have been applied to the text viewer.
168166 * Removes the first change from the queue and process it.
169- * <p>
170- * Calls {@link AbstractReconciler#initialProcess()} on entrance.
171- * </p>
172167 */
173168 @ Override
174169 public void run () {
170+ try {
171+ while (!fCanceled ) {
175172
176- delay ();
177-
178- if (fCanceled )
179- return ;
180-
181- initialProcess ();
182-
183- while (!fCanceled ) {
184-
185- delay ();
186-
187- if (fCanceled )
188- break ;
173+ delay ();
189174
190- if (!isDirty ()) {
191- waitFinish = false ; //signalWaitForFinish() was called but nothing todo
192- continue ;
193- }
175+ if (fCanceled )
176+ break ;
194177
195- synchronized (this ) {
196- if (fReset ) {
197- fReset = false ;
178+ if (!isDirty ()) {
179+ waitFinish = false ; //signalWaitForFinish() was called but nothing todo
198180 continue ;
199181 }
200- }
201182
202- DirtyRegion r = null ;
203- synchronized (fDirtyRegionQueue ) {
204- r = fDirtyRegionQueue .removeNextDirtyRegion ();
205- }
183+ synchronized (this ) {
184+ if (fReset ) {
185+ fReset = false ;
186+ continue ;
187+ }
188+ }
189+
190+ DirtyRegion r = null ;
191+ synchronized (fDirtyRegionQueue ) {
192+ r = fDirtyRegionQueue .removeNextDirtyRegion ();
193+ }
206194
207- fIsActive = true ;
195+ fIsActive = true ;
208196
209- fProgressMonitor .setCanceled (false );
197+ fProgressMonitor .setCanceled (false );
210198
211- process (r );
199+ process (r );
212200
213- synchronized (fDirtyRegionQueue ) {
214- if (0 == fDirtyRegionQueue .getSize ()) {
215- synchronized (this ) {
216- fIsDirty = fProgressMonitor .isCanceled ();
201+ synchronized (fDirtyRegionQueue ) {
202+ if (fDirtyRegionQueue .isEmpty ()) {
203+ synchronized (this ) {
204+ fIsDirty = fProgressMonitor .isCanceled ();
205+ }
206+ fDirtyRegionQueue .notifyAll ();
217207 }
218- fDirtyRegionQueue .notifyAll ();
219208 }
209+ fIsActive = false ;
220210 }
221-
222- fIsActive = false ;
211+ } finally {
212+ fIsAlive = false ;
223213 }
224214 }
225215
216+ boolean isAlive () {
217+ return fIsAlive ;
218+ }
219+
220+ /**
221+ * Star the reconciling if not running (and calls
222+ * {@link AbstractReconciler#initialProcess()}) or {@link #reset()} otherwise.
223+ */
226224 public void startReconciling () {
227- if (!isAlive ()) {
228- if (fStarted ) {
229- return ;
230- }
225+ if (!fStarted ) {
226+ fIsAlive = true ;
231227 fStarted = true ;
232- 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+ Job .createSystem ("Delayed Reconciler startup for " + fName , m -> { //$NON-NLS-1$
229+ //Until we process some code from the job, the reconciler thread is the current thread
230+ fThread = Thread . currentThread ();
231+ delay () ;
232+ if ( fCanceled ) {
233+ return Status . CANCEL_STATUS ;
234+ }
235+ initialProcess ();
236+ if ( fCanceled ) {
241237 return Status .CANCEL_STATUS ;
242238 }
239+ Thread thread = new Thread (this );
240+ thread .setName (fName );
241+ thread .setPriority (Thread .MIN_PRIORITY );
242+ thread .setDaemon (true );
243+ //we will no longer process any code here, so hand over to the worker thread.
244+ fThread = thread ;
245+ thread .start ();
246+ return Status .OK_STATUS ;
243247 }).schedule ();
244248 } else {
245249 reset ();
@@ -260,8 +264,8 @@ public void documentAboutToBeChanged(DocumentEvent e) {
260264 @ Override
261265 public void documentChanged (DocumentEvent e ) {
262266
263- if (fThread .isActive () || !fThread .isDirty () && fThread .isAlive ()) {
264- if (!fIsAllowedToModifyDocument && Thread . currentThread () == fThread )
267+ if (fWorker .isActive () || !fWorker .isDirty () && fWorker .isAlive ()) {
268+ if (!fIsAllowedToModifyDocument && isRunningInReconcilerThread () )
265269 throw new UnsupportedOperationException ("The reconciler thread is not allowed to modify the document" ); //$NON-NLS-1$
266270 aboutToBeReconciledInternal ();
267271 }
@@ -270,13 +274,13 @@ public void documentChanged(DocumentEvent e) {
270274 * The second OR condition handles the case when the document
271275 * gets changed while still inside initialProcess().
272276 */
273- if (fThread .isActive () || fThread .isDirty () && fThread .isAlive ())
277+ if (fWorker .isActive () || fWorker .isDirty () && fWorker .isAlive ())
274278 fProgressMonitor .setCanceled (true );
275279
276280 if (fIsIncrementalReconciler )
277281 createDirtyRegion (e );
278282
279- fThread .reset ();
283+ fWorker .reset ();
280284
281285 }
282286
@@ -292,11 +296,11 @@ public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput
292296 synchronized (fDirtyRegionQueue ) {
293297 fDirtyRegionQueue .purgeQueue ();
294298 }
295- if (fDocument != null && fDocument .getLength () > 0 && fThread .isDirty () && fThread .isAlive ()) {
299+ if (fDocument != null && fDocument .getLength () > 0 && fWorker .isDirty () && fWorker .isAlive ()) {
296300 DocumentEvent e = new DocumentEvent (fDocument , 0 , fDocument .getLength (), "" ); //$NON-NLS-1$
297301 createDirtyRegion (e );
298- fThread .reset ();
299- fThread .suspendCallerWhileDirty ();
302+ fWorker .reset ();
303+ fWorker .suspendCallerWhileDirty ();
300304 }
301305 }
302306
@@ -316,7 +320,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
316320
317321 fDocument .addDocumentListener (this );
318322
319- if (!fThread .isDirty ())
323+ if (!fWorker .isDirty ())
320324 aboutToBeReconciledInternal ();
321325
322326 startReconciling ();
@@ -326,7 +330,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
326330 /** Queue to manage the changes applied to the text viewer. */
327331 private DirtyRegionQueue fDirtyRegionQueue ;
328332 /** The background thread. */
329- private BackgroundThread fThread ;
333+ private BackgroundWorker fWorker ;
330334 /** Internal document and text input listener. */
331335 private Listener fListener ;
332336 /** The background thread delay. */
@@ -475,9 +479,9 @@ public void install(ITextViewer textViewer) {
475479 fViewer = textViewer ;
476480
477481 synchronized (this ) {
478- if (fThread != null )
482+ if (fWorker != null )
479483 return ;
480- fThread = new BackgroundThread (getClass ().getName ());
484+ fWorker = new BackgroundWorker (getClass ().getName ());
481485 }
482486
483487 fDirtyRegionQueue = new DirtyRegionQueue ();
@@ -511,8 +515,8 @@ public void uninstall() {
511515
512516 synchronized (this ) {
513517 // http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
514- BackgroundThread bt = fThread ;
515- fThread = null ;
518+ BackgroundWorker bt = fWorker ;
519+ fWorker = null ;
516520 bt .cancel ();
517521 }
518522 }
@@ -618,10 +622,10 @@ protected void forceReconciling() {
618622
619623 if (fDocument != null ) {
620624
621- if (!fThread .isDirty ()&& fThread .isAlive ())
625+ if (!fWorker .isDirty ()&& fWorker .isAlive ())
622626 aboutToBeReconciledInternal ();
623627
624- if (fThread .isActive ())
628+ if (fWorker .isActive ())
625629 fProgressMonitor .setCanceled (true );
626630
627631 if (fIsIncrementalReconciler ) {
@@ -638,10 +642,10 @@ protected void forceReconciling() {
638642 * Clients may extend this method.
639643 */
640644 protected synchronized void startReconciling () {
641- if (fThread == null )
645+ if (fWorker == null )
642646 return ;
643647
644- fThread .startReconciling ();
648+ fWorker .startReconciling ();
645649 }
646650
647651 /**
@@ -657,7 +661,9 @@ protected void reconcilerReset() {
657661 * @return <code>true</code> if running in this reconciler's background thread
658662 * @since 3.4
659663 */
660- protected boolean isRunningInReconcilerThread () {
661- return Thread .currentThread () == fThread ;
664+ protected synchronized boolean isRunningInReconcilerThread () {
665+ if (fWorker == null )
666+ return false ;
667+ return Thread .currentThread () == fWorker .fThread ;
662668 }
663669}
0 commit comments