Skip to content

Commit 4b0fa03

Browse files
committed
Extract Reconciler Job Into an own class
Currently the BackgroundThread is an inner class of the AbstractReconciler and is tightly coupled with it what makes it quite hard to understand the interaction between both and to properly update a reconciler on document changes or refactor the code. This is a first attempt to decouple the things by extracting the inner class in an own (package private) type to allow further refactoring operations and proper encapsulation.
1 parent 323f79d commit 4b0fa03

File tree

2 files changed

+228
-204
lines changed

2 files changed

+228
-204
lines changed

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

Lines changed: 8 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515

1616
import org.eclipse.core.runtime.Assert;
1717
import org.eclipse.core.runtime.IProgressMonitor;
18-
import org.eclipse.core.runtime.IStatus;
1918
import org.eclipse.core.runtime.NullProgressMonitor;
20-
import org.eclipse.core.runtime.Status;
2119
import org.eclipse.core.runtime.jobs.Job;
2220

2321
import org.eclipse.jface.text.DocumentEvent;
@@ -52,201 +50,6 @@
5250
*/
5351
abstract public class AbstractReconciler implements IReconciler {
5452

55-
56-
/**
57-
* Background thread for the reconciling activity.
58-
*/
59-
private class BackgroundThread extends Job {
60-
61-
/** Has the reconciler been canceled. */
62-
private boolean fCanceled= false;
63-
/** Has the reconciler been reset. */
64-
private boolean fReset= false;
65-
/** Some changes need to be processed. */
66-
private boolean fIsDirty= false;
67-
/** Is a reconciling strategy active. */
68-
private boolean fIsActive= false;
69-
70-
private volatile boolean fIsAlive;
71-
72-
private boolean started;
73-
74-
/**
75-
* Creates a new background thread. The thread
76-
* runs with minimal priority.
77-
*
78-
* @param name the thread's name
79-
*/
80-
public BackgroundThread(String name) {
81-
super(name);
82-
setPriority(Job.DECORATE);
83-
setSystem(true);
84-
}
85-
86-
/**
87-
* Returns whether a reconciling strategy is active right now.
88-
*
89-
* @return <code>true</code> if a activity is active
90-
*/
91-
public boolean isActive() {
92-
return fIsActive;
93-
}
94-
95-
/**
96-
* Returns whether some changes need to be processed.
97-
*
98-
* @return <code>true</code> if changes wait to be processed
99-
* @since 3.0
100-
*/
101-
public synchronized boolean isDirty() {
102-
return fIsDirty;
103-
}
104-
105-
/**
106-
* Cancels the background thread.
107-
*/
108-
public void doCancel() {
109-
fCanceled= true;
110-
IProgressMonitor pm= fProgressMonitor;
111-
if (pm != null)
112-
pm.setCanceled(true);
113-
synchronized (fDirtyRegionQueue) {
114-
fDirtyRegionQueue.notifyAll();
115-
}
116-
}
117-
118-
/**
119-
* Suspends the caller of this method until this background thread has
120-
* emptied the dirty region queue.
121-
*/
122-
public void suspendCallerWhileDirty() {
123-
AbstractReconciler.this.signalWaitForFinish();
124-
boolean isDirty;
125-
do {
126-
synchronized (fDirtyRegionQueue) {
127-
isDirty= fDirtyRegionQueue.getSize() > 0;
128-
if (isDirty) {
129-
try {
130-
fDirtyRegionQueue.wait();
131-
} catch (InterruptedException x) {
132-
}
133-
}
134-
}
135-
} while (isDirty);
136-
}
137-
138-
/**
139-
* Reset the background thread as the text viewer has been changed,
140-
*/
141-
public void reset() {
142-
143-
if (fDelay > 0) {
144-
145-
synchronized (this) {
146-
fIsDirty= true;
147-
fReset= true;
148-
}
149-
synchronized (fDirtyRegionQueue) {
150-
fDirtyRegionQueue.notifyAll(); // wake up wait(fDelay);
151-
}
152-
153-
} else {
154-
155-
synchronized (this) {
156-
fIsDirty= true;
157-
}
158-
159-
synchronized (fDirtyRegionQueue) {
160-
fDirtyRegionQueue.notifyAll();
161-
}
162-
}
163-
synchronized (this) {
164-
started= false;
165-
}
166-
informNotFinished();
167-
reconcilerReset();
168-
}
169-
170-
/**
171-
* The background activity. Waits until there is something in the
172-
* queue managing the changes that have been applied to the text viewer.
173-
* Removes the first change from the queue and process it.
174-
* <p>
175-
* Calls {@link AbstractReconciler#initialProcess()} on entrance.
176-
* </p>
177-
*/
178-
@Override
179-
public IStatus run(IProgressMonitor monitor) {
180-
fIsAlive= true;
181-
delay();
182-
183-
if (fCanceled)
184-
return Status.CANCEL_STATUS;
185-
186-
initialProcess();
187-
188-
while (!fCanceled) {
189-
190-
delay();
191-
192-
if (fCanceled)
193-
break;
194-
195-
if (!isDirty()) {
196-
waitFinish= false; //signalWaitForFinish() was called but nothing todo
197-
continue;
198-
}
199-
200-
synchronized (this) {
201-
if (fReset) {
202-
fReset= false;
203-
continue;
204-
}
205-
}
206-
207-
DirtyRegion r= null;
208-
synchronized (fDirtyRegionQueue) {
209-
r= fDirtyRegionQueue.removeNextDirtyRegion();
210-
}
211-
212-
fIsActive= true;
213-
214-
fProgressMonitor.setCanceled(false);
215-
216-
process(r);
217-
218-
synchronized (fDirtyRegionQueue) {
219-
if (0 == fDirtyRegionQueue.getSize()) {
220-
synchronized (this) {
221-
fIsDirty= fProgressMonitor.isCanceled();
222-
}
223-
fDirtyRegionQueue.notifyAll();
224-
}
225-
}
226-
227-
fIsActive= false;
228-
}
229-
fIsAlive= false;
230-
return Status.OK_STATUS;
231-
}
232-
233-
public boolean isAlive() {
234-
return fIsAlive;
235-
}
236-
237-
public synchronized void start() {
238-
if (!started) {
239-
started= true;
240-
schedule();
241-
}
242-
}
243-
244-
@Override
245-
public boolean belongsTo(Object family) {
246-
return family == fViewer || AbstractReconciler.class == family;
247-
}
248-
}
249-
25053
/**
25154
* Internal document listener and text input listener.
25255
*/
@@ -323,13 +126,14 @@ public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
323126
}
324127

325128
/** Queue to manage the changes applied to the text viewer. */
326-
private DirtyRegionQueue fDirtyRegionQueue;
129+
DirtyRegionQueue fDirtyRegionQueue;
327130
/** The background thread. */
328-
private BackgroundThread fThread;
131+
private ReconcilerJob fThread;
329132
/** Internal document and text input listener. */
330133
private Listener fListener;
134+
331135
/** The background thread delay. */
332-
private int fDelay= 500;
136+
int fDelay= 500;
333137
/** Signal that the the background thread should not delay. */
334138
volatile boolean waitFinish;
335139
/** Are there incremental reconciling strategies? */
@@ -476,7 +280,7 @@ public void install(ITextViewer textViewer) {
476280
synchronized (this) {
477281
if (fThread != null)
478282
return;
479-
fThread= new BackgroundThread(getClass().getName());
283+
fThread= new ReconcilerJob(getClass().getName(), this);
480284
}
481285

482286
fDirtyRegionQueue= new DirtyRegionQueue();
@@ -510,7 +314,7 @@ public void uninstall() {
510314

511315
synchronized (this) {
512316
// http://dev.eclipse.org/bugs/show_bug.cgi?id=19135
513-
BackgroundThread bt= fThread;
317+
ReconcilerJob bt= fThread;
514318
fThread= null;
515319
bt.doCancel();
516320
}
@@ -579,7 +383,7 @@ public void signalWaitForFinish() {
579383
}
580384
}
581385

582-
private void informNotFinished() {
386+
void informNotFinished() {
583387
waitFinish= false;
584388
aboutToWork();
585389
}
@@ -590,7 +394,7 @@ private void aboutToBeReconciledInternal() {
590394
}
591395

592396

593-
private void delay() {
397+
void delay() {
594398
synchronized (fDirtyRegionQueue) {
595399
if (waitFinish) {
596400
return; // do not delay when waiting;

0 commit comments

Comments
 (0)