diff options
author | Joerg Kubitz | 2021-10-24 16:03:18 +0000 |
---|---|---|
committer | Jörg Kubitz | 2022-02-06 20:31:29 +0000 |
commit | 61ad084847ff1fe178a5b8f55c3ec7e64e358014 (patch) | |
tree | 2e39b09cb157dbee81b26152229bbc45ef774f73 | |
parent | a965822c2c3d24fc50ef5191e9208b6b49ad1a8b (diff) | |
download | eclipse.platform.text-61ad084847ff1fe178a5b8f55c3ec7e64e358014.tar.gz eclipse.platform.text-61ad084847ff1fe178a5b8f55c3ec7e64e358014.tar.xz eclipse.platform.text-61ad084847ff1fe178a5b8f55c3ec7e64e358014.zip |
Bug 575864 - Add API to wake up AbstractReconciler.BackgroundThreadI20220206-1800
Avoid that Reconciler sleeps while receiver is waiting
Change-Id: I582fd963815748e1f9e14a1f9f5313cbe53ca627
Signed-off-by: Joerg Kubitz <jkubitz-eclipse@gmx.de>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.text/+/186867
Tested-by: Platform Bot <platform-bot@eclipse.org>
6 files changed, 105 insertions, 18 deletions
diff --git a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF index 0ac00e4dd9f..36a3e53c7eb 100644 --- a/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.jface.text.tests/META-INF/MANIFEST.MF @@ -16,7 +16,7 @@ Export-Package: org.eclipse.jface.text.tests.templates.persistence, org.eclipse.jface.text.tests.util Require-Bundle: - org.eclipse.jface.text;bundle-version="[3.19.0,4.0.0)", + org.eclipse.jface.text;bundle-version="[3.20.0,4.0.0)", org.eclipse.jface;bundle-version="[3.5.0,4.0.0)", org.junit;bundle-version="4.12.0", org.eclipse.text.tests;bundle-version="[3.5.0,4.0.0)", diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java index 9668ad7342d..5ea29e85179 100644 --- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java @@ -25,6 +25,7 @@ import org.eclipse.jface.text.tests.contentassist.ContextInformationTest; import org.eclipse.jface.text.tests.contentassist.FilteringAsyncContentAssistTests; import org.eclipse.jface.text.tests.contentassist.IncrementalAsyncContentAssistTests; import org.eclipse.jface.text.tests.reconciler.AbstractReconcilerTest; +import org.eclipse.jface.text.tests.reconciler.FastAbstractReconcilerTest; import org.eclipse.jface.text.tests.rules.DefaultPartitionerTest; import org.eclipse.jface.text.tests.rules.DefaultPartitionerZeroLengthTest; import org.eclipse.jface.text.tests.rules.FastPartitionerTest; @@ -59,6 +60,7 @@ import org.eclipse.jface.text.tests.templates.persistence.TemplatePersistenceDat ContextInformationPresenterTest.class, AbstractReconcilerTest.class, + FastAbstractReconcilerTest.class, DefaultPartitionerTest.class, DefaultPartitionerZeroLengthTest.class, diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/AbstractReconcilerTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/AbstractReconcilerTest.java index 134c59d4b0e..9778c251510 100644 --- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/AbstractReconcilerTest.java +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/AbstractReconcilerTest.java @@ -164,6 +164,10 @@ public class AbstractReconcilerTest { fCallLog.add("reconcilerDocumentChanged"); } @Override + protected void aboutToWork() { + AbstractReconcilerTest.this.aboutToWork(this); + } + @Override protected void aboutToBeReconciled() { fCallLog.add("aboutToBeReconciled"); } @@ -177,7 +181,7 @@ public class AbstractReconcilerTest { } }; fReconciler.setIsIncrementalReconciler(false); - fReconciler.setDelay(50); // make tests run faster + fReconciler.setDelay(getDelay()); fProgressMonitor= new NullProgressMonitor(); fReconciler.setProgressMonitor(fProgressMonitor); @@ -190,6 +194,14 @@ public class AbstractReconcilerTest { fAccessor= new Accessor(object, object.getClass()); } + int getDelay() { + return 50; // make tests run faster + } + + void aboutToWork(@SuppressWarnings("unused") AbstractReconciler reconciler) { + // nothing + } + @After public void tearDown() throws Exception { fBarrier.shutdown(); diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/FastAbstractReconcilerTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/FastAbstractReconcilerTest.java new file mode 100644 index 00000000000..e68fc857a34 --- /dev/null +++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/reconciler/FastAbstractReconcilerTest.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2021 Joerg Kubitz. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Joerg Kubitz - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.text.tests.reconciler; + +import org.eclipse.jface.text.reconciler.AbstractReconciler; + +public class FastAbstractReconcilerTest extends AbstractReconcilerTest { + + @Override + int getDelay() { + return 10000; // make tests run slower (too slow without signalWaitForFinish) + } + + @Override + void aboutToWork(AbstractReconciler reconciler) { + reconciler.signalWaitForFinish(); // make tests run faster (instant) + } +} diff --git a/org.eclipse.jface.text/META-INF/MANIFEST.MF b/org.eclipse.jface.text/META-INF/MANIFEST.MF index 377e97e3900..bf15c525c29 100644 --- a/org.eclipse.jface.text/META-INF/MANIFEST.MF +++ b/org.eclipse.jface.text/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jface.text -Bundle-Version: 3.19.100.qualifier +Bundle-Version: 3.20.0.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Export-Package: diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java index 8b61857ba42..296dc543606 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/reconciler/AbstractReconciler.java @@ -113,6 +113,7 @@ abstract public class AbstractReconciler implements IReconciler { * emptied the dirty region queue. */ public void suspendCallerWhileDirty() { + AbstractReconciler.this.signalWaitForFinish(); boolean isDirty; do { synchronized (fDirtyRegionQueue) { @@ -150,6 +151,7 @@ abstract public class AbstractReconciler implements IReconciler { } } + informNotFinished(); reconcilerReset(); } @@ -164,12 +166,7 @@ abstract public class AbstractReconciler implements IReconciler { @Override public void run() { - synchronized (fDirtyRegionQueue) { - try { - fDirtyRegionQueue.wait(fDelay); - } catch (InterruptedException x) { - } - } + delay(); if (fCanceled) return; @@ -178,12 +175,7 @@ abstract public class AbstractReconciler implements IReconciler { while (!fCanceled) { - synchronized (fDirtyRegionQueue) { - try { - fDirtyRegionQueue.wait(fDelay); - } catch (InterruptedException x) { - } - } + delay(); if (fCanceled) break; @@ -238,7 +230,7 @@ abstract public class AbstractReconciler implements IReconciler { if (fThread.isActive() || !fThread.isDirty() && fThread.isAlive()) { if (!fIsAllowedToModifyDocument && Thread.currentThread() == fThread) throw new UnsupportedOperationException("The reconciler thread is not allowed to modify the document"); //$NON-NLS-1$ - aboutToBeReconciled(); + aboutToBeReconciledInternal(); } /* @@ -292,7 +284,7 @@ abstract public class AbstractReconciler implements IReconciler { fDocument.addDocumentListener(this); if (!fThread.isDirty()) - aboutToBeReconciled(); + aboutToBeReconciledInternal(); startReconciling(); } @@ -306,6 +298,8 @@ abstract public class AbstractReconciler implements IReconciler { private Listener fListener; /** The background thread delay. */ private int fDelay= 500; + /** Signal that the the background thread should not delay. */ + volatile boolean waitFinish; /** Are there incremental reconciling strategies? */ private boolean fIsIncrementalReconciler= true; /** The progress monitor used by this reconciler. */ @@ -527,6 +521,56 @@ abstract public class AbstractReconciler implements IReconciler { } /** + * Hook for subclasses which want to perform some action as soon as the reconciler starts work + * (initial or reconciling) or waiting. + * <p> + * Default implementation is to do nothing. Implementors may call + * {@link #signalWaitForFinish()}. + * </p> + * + * @since 3.20 + * @see #signalWaitForFinish + */ + protected void aboutToWork() { + } + + /** + * Signal reconciling should finish as soon as possible. + * + * @since 3.20 + * @see #aboutToWork + */ + public void signalWaitForFinish() { + synchronized (fDirtyRegionQueue) { + waitFinish= true; + fDirtyRegionQueue.notifyAll(); // notify AbstractReconciler#delay about waitFinish + } + } + + private void informNotFinished() { + waitFinish= false; + aboutToWork(); + } + + private void aboutToBeReconciledInternal() { + aboutToBeReconciled(); + informNotFinished(); + } + + + private void delay() { + synchronized (fDirtyRegionQueue) { + if (waitFinish) { + return; // do not delay when waiting; + } + try { + fDirtyRegionQueue.wait(fDelay); + } catch (InterruptedException x) { + } + } + } + + /** * This method is called on startup of the background activity. It is called only * once during the life time of the reconciler. Clients may reimplement this method. */ @@ -542,7 +586,7 @@ abstract public class AbstractReconciler implements IReconciler { if (fDocument != null) { if (!fThread.isDirty()&& fThread.isAlive()) - aboutToBeReconciled(); + aboutToBeReconciledInternal(); if (fThread.isActive()) fProgressMonitor.setCanceled(true); |