diff options
author | Stefan Xenos | 2016-08-31 00:37:08 +0000 |
---|---|---|
committer | Stefan Xenos | 2016-08-31 00:37:08 +0000 |
commit | b3bdb7f21fd25f056de062d902fec8e286a4572f (patch) | |
tree | 3cb428ef5cfb88db6711f8d0bd55ec91e51ad829 | |
parent | 04d0bef8bc6079faf513c7e893ec321dc4e9b3d9 (diff) | |
download | rt.equinox.bundles-b3bdb7f21fd25f056de062d902fec8e286a4572f.tar.gz rt.equinox.bundles-b3bdb7f21fd25f056de062d902fec8e286a4572f.tar.xz rt.equinox.bundles-b3bdb7f21fd25f056de062d902fec8e286a4572f.zip |
Bug 500483 - Offer a cancellation-checking variant of Submonitor#worked
Change-Id: I0a2d3bceaaf5b80eaeb55699209f89bdb6dfb6b3
Signed-off-by: Stefan Xenos <sxenos@gmail.com>
3 files changed, 81 insertions, 14 deletions
diff --git a/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF index bba5bec7a..af3acd295 100644 --- a/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.common/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.equinox.common; singleton:=true -Bundle-Version: 3.8.100.qualifier +Bundle-Version: 3.9.0.qualifier Bundle-Localization: plugin Export-Package: org.eclipse.core.internal.boot;x-friends:="org.eclipse.core.resources,org.eclipse.core.runtime.compatibility,org.eclipse.pde.build", org.eclipse.core.internal.runtime;common=split;mandatory:=common; diff --git a/bundles/org.eclipse.equinox.common/pom.xml b/bundles/org.eclipse.equinox.common/pom.xml index bc207207d..0ad1c078c 100644 --- a/bundles/org.eclipse.equinox.common/pom.xml +++ b/bundles/org.eclipse.equinox.common/pom.xml @@ -19,6 +19,6 @@ </parent> <groupId>org.eclipse.equinox</groupId> <artifactId>org.eclipse.equinox.common</artifactId> - <version>3.8.100-SNAPSHOT</version> + <version>3.9.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/SubMonitor.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/SubMonitor.java index 9ec1f7705..14e278a8a 100644 --- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/SubMonitor.java +++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/SubMonitor.java @@ -69,7 +69,7 @@ import org.eclipse.core.internal.runtime.TracingOptions; * doSomeWork(progress.split(30)); * * // Advance the monitor by another 30% - * progress.worked(30); + * progress.step(30); * * // Use the remaining 40% of the progress to do some more work * doSomeWork(progress.split(40)); @@ -110,7 +110,7 @@ import org.eclipse.core.internal.runtime.TracingOptions; * } else { * // Bad: Causes the progress monitor to appear to start at 50%, wasting half of the * // space in the monitor. - * progress.worked(50); + * progress.step(50); * } * </pre> * @@ -171,14 +171,41 @@ import org.eclipse.core.internal.runtime.TracingOptions; public final class SubMonitor implements IProgressMonitorWithBlocking { /** - * Number of trivial operations (operations which do not report any progress) which can be + * Number of trivial split operations (operations which do not report any progress) which can be * performed before the monitor performs a cancellation check. This ensures that cancellation * checks do not create a performance problem in tight loops that create a lot of SubMonitors, * while still ensuring that cancellation is checked occasionally in such loops. This only * affects operations which are too small to report any progress. Operations which are large * enough to consume at least one tick will always be checked for cancellation. */ - private static final int TRIVIAL_OPERATIONS_BEFORE_CANCELLATION_CHECK = 10; + private static final int TRIVIAL_SPLITS_BEFORE_CANCELLATION_CHECK = 10; + + /** + * Number of trivial tick operations (operations which do not report any progress) which can be + * performed before the monitor performs a cancellation check. This ensures that cancellation + * checks do not create a performance problem in tight loops that report a lot of work + * while still ensuring that cancellation is checked occasionally in such loops. This only + * affects operations which are too small to report any progress. Operations which are large + * enough to consume at least one tick will always be checked for cancellation. + */ + private static final int TRIVIAL_TICKS_BEFORE_CANCELLATION_CHECK = 10; + + /** + * The limit for {@link RootInfo#cancellationCheckCounter} before performing a cancellation check. + */ + private static final int TRIVIAL_OPERATION_COUNT_LIMIT = TRIVIAL_SPLITS_BEFORE_CANCELLATION_CHECK * TRIVIAL_TICKS_BEFORE_CANCELLATION_CHECK; + + /** + * Amount to increment {@link RootInfo#cancellationCheckCounter} when performing + * a trivial {@link #split(int)} operation. + */ + private static final int TRIVIAL_SPLIT_DELTA = TRIVIAL_OPERATION_COUNT_LIMIT / TRIVIAL_SPLITS_BEFORE_CANCELLATION_CHECK; + + /** + * Amount to increment {@link RootInfo#cancellationCheckCounter} when performing + * a trivial {@link #step(int)} operation. + */ + private static final int TRIVIAL_TICK_DELTA = TRIVIAL_OPERATION_COUNT_LIMIT / TRIVIAL_TICKS_BEFORE_CANCELLATION_CHECK;; /** * Minimum number of ticks to allocate when calling beginTask on an unknown IProgressMonitor. @@ -266,6 +293,15 @@ public final class SubMonitor implements IProgressMonitorWithBlocking { throw new OperationCanceledException(); } } + + public void reportTrivialOperation(int cancellationDelta) { + cancellationCheckCounter += cancellationDelta; + // This is a trivial operation. Only perform a cancellation check after the counter expires. + if (cancellationCheckCounter >= TRIVIAL_OPERATION_COUNT_LIMIT) { + cancellationCheckCounter = 0; + checkForCancellation(); + } + } } /** @@ -685,7 +721,7 @@ public final class SubMonitor implements IProgressMonitorWithBlocking { * * //////////////////////////////////////////////////////////////////////////// * // Example 2: Demonstrates the function of active children. Creating children - * // is sufficient to smoothly report progress, even if worked(...) and done() + * // is sufficient to smoothly report progress, even if step(...) and done() * // are never called. * void myMethod(IProgressMonitor parent) { * SubMonitor progress = SubMonitor.convert(parent, 100); @@ -789,7 +825,7 @@ public final class SubMonitor implements IProgressMonitorWithBlocking { * * //////////////////////////////////////////////////////////////////////////// * // Example 2: Demonstrates the function of active children. Creating children - * // is sufficient to smoothly report progress, even if worked(...) and done() + * // is sufficient to smoothly report progress, even if step(...) and done() * // are never called. * void myMethod(IProgressMonitor parent) { * SubMonitor progress = SubMonitor.convert(parent, 100); @@ -860,7 +896,7 @@ public final class SubMonitor implements IProgressMonitorWithBlocking { * * //////////////////////////////////////////////////////////////////////////// * // Example 2: Demonstrates the function of active children. Creating children - * // is sufficient to smoothly report progress, even if worked(...) and done() + * // is sufficient to smoothly report progress, even if step(...) and done() * // are never called. * void myMethod(IProgressMonitor parent) { * SubMonitor progress = SubMonitor.convert(parent, 100); @@ -917,16 +953,47 @@ public final class SubMonitor implements IProgressMonitorWithBlocking { root.checkForCancellation(); } } else { - // This is a trivial operation. Only perform a cancellation check after the counter expires. - if (++root.cancellationCheckCounter >= TRIVIAL_OPERATIONS_BEFORE_CANCELLATION_CHECK) { - root.cancellationCheckCounter = 0; - root.checkForCancellation(); - } + root.reportTrivialOperation(TRIVIAL_SPLIT_DELTA); } } return result; } + /** + * Notifies that a given number of work units of the main task + * has been completed. Note that this amount represents an + * installment, as opposed to a cumulative amount of work done + * to date. + * <p> + * This method is much like {@link #worked}, but will additionally check for cancellation and + * will throw an {@link OperationCanceledException} if the monitor has been cancelled. Not + * every call to this method will trigger a cancellation check. The checks will be performed + * as often as possible without degrading the performance of the caller. + * + * @param work a non-negative number of work units just completed + * @throws OperationCanceledException if the monitor has been cancelled + * @since 3.9 + */ + public void step(int work) throws OperationCanceledException { + if (TracingOptions.debugProgressMonitors) { + if (work == 0) { + logProblem("Attempted to report 0 ticks of work"); //$NON-NLS-1$ + } else if (work < 0) { + logProblem("Attempted to report negative ticks of work"); //$NON-NLS-1$ + } + } + + cleanupActiveChild(); + + int delta = consume(Math.max(work, 0)); + if (delta != 0) { + root.checkForCancellation(); + root.worked(delta); + } else { + root.reportTrivialOperation(TRIVIAL_TICK_DELTA); + } + } + private void cleanupActiveChild() { if (lastSubMonitor == null) return; |