@@ -55,29 +55,27 @@ abstract public class AbstractReconciler implements IReconciler {
55
55
/**
56
56
* Background thread for the reconciling activity.
57
57
*/
58
- class BackgroundThread extends Thread {
58
+ class BackgroundWorker implements Runnable {
59
59
60
60
/** Has the reconciler been canceled. */
61
- private boolean fCanceled = false ;
61
+ private boolean fCanceled ;
62
62
/** Has the reconciler been reset. */
63
- private boolean fReset = false ;
63
+ private boolean fReset ;
64
64
/** Some changes need to be processed. */
65
- private boolean fIsDirty = false ;
65
+ private boolean fIsDirty ;
66
66
/** Is a reconciling strategy active. */
67
- private boolean fIsActive = false ;
67
+ private boolean fIsActive ;
68
68
69
69
private boolean fStarted ;
70
70
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 ;
81
79
}
82
80
83
81
/**
@@ -166,80 +164,86 @@ public void reset() {
166
164
* The background activity. Waits until there is something in the
167
165
* queue managing the changes that have been applied to the text viewer.
168
166
* Removes the first change from the queue and process it.
169
- * <p>
170
- * Calls {@link AbstractReconciler#initialProcess()} on entrance.
171
- * </p>
172
167
*/
173
168
@ Override
174
169
public void run () {
170
+ try {
171
+ while (!fCanceled ) {
175
172
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 ();
189
174
190
- if (!isDirty ()) {
191
- waitFinish = false ; //signalWaitForFinish() was called but nothing todo
192
- continue ;
193
- }
175
+ if (fCanceled )
176
+ break ;
194
177
195
- synchronized (this ) {
196
- if (fReset ) {
197
- fReset = false ;
178
+ if (!isDirty ()) {
179
+ waitFinish = false ; //signalWaitForFinish() was called but nothing todo
198
180
continue ;
199
181
}
200
- }
201
182
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
+ }
206
194
207
- fIsActive = true ;
195
+ fIsActive = true ;
208
196
209
- fProgressMonitor .setCanceled (false );
197
+ fProgressMonitor .setCanceled (false );
210
198
211
- process (r );
199
+ process (r );
212
200
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 ();
217
207
}
218
- fDirtyRegionQueue .notifyAll ();
219
208
}
209
+ fIsActive = false ;
220
210
}
221
-
222
- fIsActive = false ;
211
+ } finally {
212
+ fIsAlive = false ;
223
213
}
224
214
}
225
215
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
+ */
226
224
public void startReconciling () {
227
- if (!isAlive ()) {
228
- if (fStarted ) {
229
- return ;
230
- }
225
+ if (!fStarted ) {
226
+ fIsAlive = true ;
231
227
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 ) {
241
237
return Status .CANCEL_STATUS ;
242
238
}
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 ;
243
247
}).schedule ();
244
248
} else {
245
249
reset ();
@@ -260,8 +264,8 @@ public void documentAboutToBeChanged(DocumentEvent e) {
260
264
@ Override
261
265
public void documentChanged (DocumentEvent e ) {
262
266
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 () )
265
269
throw new UnsupportedOperationException ("The reconciler thread is not allowed to modify the document" ); //$NON-NLS-1$
266
270
aboutToBeReconciledInternal ();
267
271
}
@@ -270,13 +274,13 @@ public void documentChanged(DocumentEvent e) {
270
274
* The second OR condition handles the case when the document
271
275
* gets changed while still inside initialProcess().
272
276
*/
273
- if (fThread .isActive () || fThread .isDirty () && fThread .isAlive ())
277
+ if (fWorker .isActive () || fWorker .isDirty () && fWorker .isAlive ())
274
278
fProgressMonitor .setCanceled (true );
275
279
276
280
if (fIsIncrementalReconciler )
277
281
createDirtyRegion (e );
278
282
279
- fThread .reset ();
283
+ fWorker .reset ();
280
284
281
285
}
282
286
@@ -292,11 +296,11 @@ public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput
292
296
synchronized (fDirtyRegionQueue ) {
293
297
fDirtyRegionQueue .purgeQueue ();
294
298
}
295
- if (fDocument != null && fDocument .getLength () > 0 && fThread .isDirty () && fThread .isAlive ()) {
299
+ if (fDocument != null && fDocument .getLength () > 0 && fWorker .isDirty () && fWorker .isAlive ()) {
296
300
DocumentEvent e = new DocumentEvent (fDocument , 0 , fDocument .getLength (), "" ); //$NON-NLS-1$
297
301
createDirtyRegion (e );
298
- fThread .reset ();
299
- fThread .suspendCallerWhileDirty ();
302
+ fWorker .reset ();
303
+ fWorker .suspendCallerWhileDirty ();
300
304
}
301
305
}
302
306
@@ -316,7 +320,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
316
320
317
321
fDocument .addDocumentListener (this );
318
322
319
- if (!fThread .isDirty ())
323
+ if (!fWorker .isDirty ())
320
324
aboutToBeReconciledInternal ();
321
325
322
326
startReconciling ();
@@ -326,7 +330,7 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
326
330
/** Queue to manage the changes applied to the text viewer. */
327
331
private DirtyRegionQueue fDirtyRegionQueue ;
328
332
/** The background thread. */
329
- private BackgroundThread fThread ;
333
+ private BackgroundWorker fWorker ;
330
334
/** Internal document and text input listener. */
331
335
private Listener fListener ;
332
336
/** The background thread delay. */
@@ -475,9 +479,9 @@ public void install(ITextViewer textViewer) {
475
479
fViewer = textViewer ;
476
480
477
481
synchronized (this ) {
478
- if (fThread != null )
482
+ if (fWorker != null )
479
483
return ;
480
- fThread = new BackgroundThread (getClass ().getName ());
484
+ fWorker = new BackgroundWorker (getClass ().getName ());
481
485
}
482
486
483
487
fDirtyRegionQueue = new DirtyRegionQueue ();
@@ -511,8 +515,8 @@ public void uninstall() {
511
515
512
516
synchronized (this ) {
513
517
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
514
- BackgroundThread bt = fThread ;
515
- fThread = null ;
518
+ BackgroundWorker bt = fWorker ;
519
+ fWorker = null ;
516
520
bt .cancel ();
517
521
}
518
522
}
@@ -618,10 +622,10 @@ protected void forceReconciling() {
618
622
619
623
if (fDocument != null ) {
620
624
621
- if (!fThread .isDirty ()&& fThread .isAlive ())
625
+ if (!fWorker .isDirty ()&& fWorker .isAlive ())
622
626
aboutToBeReconciledInternal ();
623
627
624
- if (fThread .isActive ())
628
+ if (fWorker .isActive ())
625
629
fProgressMonitor .setCanceled (true );
626
630
627
631
if (fIsIncrementalReconciler ) {
@@ -638,10 +642,10 @@ protected void forceReconciling() {
638
642
* Clients may extend this method.
639
643
*/
640
644
protected synchronized void startReconciling () {
641
- if (fThread == null )
645
+ if (fWorker == null )
642
646
return ;
643
647
644
- fThread .startReconciling ();
648
+ fWorker .startReconciling ();
645
649
}
646
650
647
651
/**
@@ -657,7 +661,9 @@ protected void reconcilerReset() {
657
661
* @return <code>true</code> if running in this reconciler's background thread
658
662
* @since 3.4
659
663
*/
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 ;
662
668
}
663
669
}
0 commit comments