Skip to content

Commit 4fe3827

Browse files
implemented a fix for fireModelchanged() with unsync fModelEvent
1 parent 9dee7b7 commit 4fe3827

File tree

4 files changed

+82
-11
lines changed

4 files changed

+82
-11
lines changed

bundles/org.eclipse.text/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.text
5-
Bundle-Version: 3.14.500.qualifier
5+
Bundle-Version: 3.14.600.qualifier
66
Bundle-Vendor: %providerName
77
Bundle-Localization: plugin
88
Export-Package:

bundles/org.eclipse.text/src/org/eclipse/jface/text/source/AnnotationModel.java

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Collections;
2020
import java.util.IdentityHashMap;
2121
import java.util.Iterator;
22+
import java.util.LinkedList;
2223
import java.util.List;
2324
import java.util.Map;
2425
import java.util.Map.Entry;
@@ -27,6 +28,10 @@
2728
import java.util.concurrent.ConcurrentHashMap;
2829

2930
import org.eclipse.core.runtime.Assert;
31+
import org.eclipse.core.runtime.IProgressMonitor;
32+
import org.eclipse.core.runtime.IStatus;
33+
import org.eclipse.core.runtime.Status;
34+
import org.eclipse.core.runtime.jobs.Job;
3035

3136
import org.eclipse.jface.text.AbstractDocument;
3237
import org.eclipse.jface.text.BadLocationException;
@@ -48,6 +53,45 @@
4853
*/
4954
public class AnnotationModel implements IAnnotationModel, IAnnotationModelExtension, IAnnotationModelExtension2, ISynchronizable {
5055

56+
/**
57+
* This job is replacing the original thread, to make it multi thread safe (fixes the race
58+
* condition of fModelEvent)
59+
*/
60+
private final class FireModelChangeJob extends Job {
61+
62+
private LinkedList<AnnotationModelEvent> events= new LinkedList<>();
63+
64+
private FireModelChangeJob() {
65+
super(Messages.AnnotationModel_FireModelChangedEventJobTitle);
66+
}
67+
68+
@Override
69+
protected IStatus run(IProgressMonitor monitor) {
70+
synchronized (events) {
71+
AnnotationModelEvent nextEvent= events.poll();
72+
while (nextEvent != null) {
73+
fireModelChanged(nextEvent);
74+
nextEvent= events.poll();
75+
}
76+
}
77+
return Status.OK_STATUS;
78+
}
79+
80+
/**
81+
* Adds a new {@link AnnotationModelEvent} to the events list to fire it in the job
82+
* execution. If job is running
83+
*
84+
* @param event the event to fire.
85+
*/
86+
public void fireDelayedModelChangedEvent(AnnotationModelEvent event) {
87+
if (event != null) {
88+
synchronized (events) {
89+
events.add(event);
90+
}
91+
schedule();
92+
}
93+
}
94+
}
5195

5296
/**
5397
* Iterator that returns the annotations for a given region.
@@ -307,6 +351,12 @@ public void modelChanged(AnnotationModelEvent event) {
307351
*/
308352
private Object fModificationStamp= new Object();
309353

354+
/**
355+
* The job for firing the model changes
356+
* @since 3.14
357+
*/
358+
private FireModelChangeJob modelChangedEventJob;
359+
310360
/**
311361
* Creates a new annotation model. The annotation is empty, i.e. does not
312362
* manage any annotations and is not connected to any document.
@@ -315,6 +365,7 @@ public AnnotationModel() {
315365
fAnnotations= new AnnotationMap(10);
316366
fPositions= new IdentityHashMap<>(10);
317367
fAnnotationModelListeners= new ArrayList<>(2);
368+
modelChangedEventJob = new FireModelChangeJob();
318369

319370
fDocumentListener= new IDocumentListener() {
320371

@@ -667,10 +718,10 @@ protected void cleanup(boolean fireModelChanged) {
667718
/**
668719
* Removes all annotations from the model whose associated positions have been
669720
* deleted. If requested inform all model listeners about the change. If requested
670-
* a new thread is created for the notification of the model listeners.
721+
* a new job is created for the notification of the model listeners.
671722
*
672723
* @param fireModelChanged indicates whether to notify all model listeners
673-
* @param forkNotification <code>true</code> iff notification should be done in a new thread
724+
* @param forkNotification <code>true</code> if notification should be done in a new job
674725
* @since 3.0
675726
*/
676727
private void cleanup(boolean fireModelChanged, boolean forkNotification) {
@@ -692,14 +743,7 @@ private void cleanup(boolean fireModelChanged, boolean forkNotification) {
692743
if (fireModelChanged && forkNotification) {
693744
removeAnnotations(deleted, false, false);
694745
synchronized (getLockObject()) {
695-
if (fModelEvent != null) {
696-
new Thread() {
697-
@Override
698-
public void run() {
699-
fireModelChanged();
700-
}
701-
}.start();
702-
}
746+
modelChangedEventJob.fireDelayedModelChangedEvent(fModelEvent);
703747
}
704748
} else {
705749
removeAnnotations(deleted, fireModelChanged, false);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.eclipse.jface.text.source;
2+
3+
import org.eclipse.osgi.util.NLS;
4+
5+
/**
6+
* @since 3.14
7+
*/
8+
public class Messages extends NLS {
9+
10+
/**
11+
* @since 3.14
12+
*/
13+
private static final String BUNDLE_NAME= Messages.class.getPackageName() + ".messages"; //$NON-NLS-1$
14+
15+
/**
16+
* @since 3.14
17+
*/
18+
public static String AnnotationModel_FireModelChangedEventJobTitle;
19+
static {
20+
// initialize resource bundle
21+
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
22+
}
23+
24+
private Messages() {
25+
}
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AnnotationModel_FireModelChangedEventJobTitle=Fire model changed event

0 commit comments

Comments
 (0)