From 058e6f554c9480032ffb13b167a712a22b9ea719 Mon Sep 17 00:00:00 2001
From: teicher
Date: Wed, 31 Mar 2004 13:35:04 +0000
Subject: fixes bug 56871: [implementation] ConcurrentModificationException is
thrown occasionally at IDocumentProvider::add/removeElementStateListener()
---
.../quickdiff/LastSaveReferenceProvider.java | 54 +++++++++++++++++++---
1 file changed, 47 insertions(+), 7 deletions(-)
(limited to 'org.eclipse.ui.editors')
diff --git a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
index 7c8cd34ddb1..c6942354da7 100644
--- a/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
+++ b/org.eclipse.ui.editors/src/org/eclipse/ui/internal/editors/quickdiff/LastSaveReferenceProvider.java
@@ -25,11 +25,14 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.widgets.Display;
+
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.editors.text.IStorageDocumentProvider;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.IElementStateListener;
@@ -67,6 +70,8 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
* operation, or null
.
*/
private IProgressMonitor fProgressMonitor;
+ /** The text editor we run upon. */
+ private ITextEditor fEditor;
/**
* A job to put the reading of file contents into a background.
@@ -109,21 +114,22 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
* {@inheritdoc}
*/
public void dispose() {
- IDocumentProvider provider= fDocumentProvider;
- if (provider != null)
- provider.removeElementStateListener(this);
-
IProgressMonitor monitor= fProgressMonitor;
if (monitor != null) {
monitor.setCanceled(true);
}
+ IDocumentProvider provider= fDocumentProvider;
+
synchronized (fLock) {
+ if (provider != null)
+ provider.removeElementStateListener(this);
fEditorInput= null;
fDocumentProvider= null;
fReference= null;
fDocumentRead= false;
fProgressMonitor= null;
+ fEditor= null;
}
}
@@ -145,11 +151,13 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
input= targetEditor.getEditorInput();
}
+
// dispose if the editor input or document provider have changed
// note that they may serve multiple editors
if (provider != fDocumentProvider || input != fEditorInput) {
dispose();
synchronized (fLock) {
+ fEditor= targetEditor;
fDocumentProvider= provider;
fEditorInput= input;
}
@@ -184,6 +192,7 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
IDocumentProvider prov= fDocumentProvider;
IEditorInput inp= fEditorInput;
IDocument doc= fReference;
+ ITextEditor editor= fEditor;
if (prov instanceof IStorageDocumentProvider && inp instanceof IFileEditorInput) {
@@ -196,9 +205,6 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
else
return;
- // addElementStateListener adds at most once - no problem to call
- // repeatedly
- ((IDocumentProvider) provider).addElementStateListener(this);
IJobManager jobMgr= Platform.getJobManager();
IFile file= input.getFile();
@@ -243,6 +249,7 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
// been updated in between (dispose or setActiveEditor)
fReference= doc;
fDocumentRead= true;
+ addElementStateListener(editor, prov);
}
}
}
@@ -250,6 +257,39 @@ public class LastSaveReferenceProvider implements IQuickDiffProviderImplementati
/* utility methods */
+ /**
+ * Adds this as element state listener in the UI thread as it can otherwise
+ * conflict with other listener additions, since DocumentProvider is not
+ * threadsafe.
+ *
+ * @param editor the editor to get the display from
+ * @param provider the document provider to register as element state listener
+ */
+ private void addElementStateListener(ITextEditor editor, final IDocumentProvider provider) {
+ // addElementStateListener adds at most once - no problem to call
+ // repeatedly
+ Runnable runnable= new Runnable() {
+ public void run() {
+ synchronized (fLock) {
+ if (fDocumentProvider == provider)
+ provider.addElementStateListener(LastSaveReferenceProvider.this);
+ }
+ }
+ };
+
+ Display display= null;
+ if (editor != null) {
+ IWorkbenchPartSite site= editor.getSite();
+ if (site != null)
+ site.getWorkbenchWindow().getShell().getDisplay();
+ }
+
+ if (display != null && !display.isDisposed())
+ display.asyncExec(runnable);
+ else
+ runnable.run();
+ }
+
/**
* Gets the contents of file
as an input stream.
*
--
cgit v1.2.3