1 /*******************************************************************************
2  * Copyright (c) 2006, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Stefan Xenos - initial API and implementation
13  *     Stefan Xenos - bug 174539 - add a 1-argument convert(...) method
14  *     Stefan Xenos - bug 174040 - SubMonitor#convert doesn't always set task name
15  *     Stefan Xenos - bug 206942 - updated javadoc to recommend better constants for infinite progress
16  *     Stefan Xenos (Google) - bug 475747 - Support efficient, convenient cancellation checks in SubMonitor
17  *     Stefan Xenos (Google) - bug 476924 - Add a SUPPRESS_ISCANCELED flag to SubMonitor
18  *     IBM Corporation - ongoing maintenance
19  *******************************************************************************/
20 package org.eclipse.core.runtime;
21 
22 import java.util.HashSet;
23 import java.util.Set;
24 import org.eclipse.core.internal.runtime.RuntimeLog;
25 import org.eclipse.core.internal.runtime.TracingOptions;
26 
27 /**
28  * <p>A progress monitor that uses a given amount of work ticks from a parent monitor. This is intended as a
29  * safer, easier-to-use alternative to SubProgressMonitor. The main benefits of SubMonitor over
30  * SubProgressMonitor are:</p>
31  * <ul>
32  * <li>It is not necessary to call beginTask() or done() on an instance of SubMonitor.</li>
33  * <li>SubMonitor has a simpler syntax for creating nested monitors.</li>
34  * <li>SubMonitor is more efficient for deep recursion chains.</li>
35  * <li>SubMonitor has a setWorkRemaining method that allows the remaining space on the monitor to be
36  * redistributed without reporting any work.</li>
37  * <li>SubMonitor protects the caller from common progress reporting bugs in a called method. For example,
38  * if a called method fails to call done() on the given monitor or fails to consume all the ticks on
39  * the given monitor, the parent will correct the problem after the method returns.</li>
40  * </ul>
41  * <p><b>USAGE:</b></p>
42  *
43  * <p>When implementing a method that accepts an IProgressMonitor:</p>
44  * <ul>
45  * <li>At the start of your method, use <code>SubMonitor.convert(...).</code> to convert the IProgressMonitor
46  * into a SubMonitor. </li>
47  * <li>Use <code>SubMonitor.split(...)</code> whenever you need to call another method that
48  * accepts an IProgressMonitor.</li>
49  * </ul>
50  *
51  * <p><b>Example: Recommended usage</b></p>
52  *
53  * <p>This example demonstrates how the recommended usage of <code>SubMonitor</code> makes it unnecessary to call
54  * IProgressMonitor.done() in most situations.</p>
55  *
56  * <p>It is never necessary to call done() on a monitor obtained from <code>convert</code> or <code>progress.split()</code>.
57  * In this example, there is no guarantee that <code>monitor</code> is an instance of <code>SubMonitor</code>, making it
58  * necessary to call <code>monitor.done()</code>. The JavaDoc contract makes this the responsibility of the caller.</p>
59  *
60  * <pre>
61  *      // {@literal @}param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
62  *      //        to call done() on the given monitor. Accepts <code>null</code>, indicating that no progress should be
63  *      //        reported and that the operation cannot be cancelled.
64  *      //
65  *      void doSomething(IProgressMonitor monitor) {
66  *          // Convert the given monitor into a progress instance
67  *          SubMonitor progress = SubMonitor.convert(monitor, 100);
68  *
69  *          // Use 30% of the progress to do some work
70  *          doSomeWork(progress.split(30));
71  *
72  *          // Advance the monitor by another 30%
73  *          progress.split(30);
74  *
75  *          // Use the remaining 40% of the progress to do some more work
76  *          doSomeWork(progress.split(40));
77  *      }
78  * </pre>
79  *
80  * <p><b>Example: Branches</b></p>
81  *
82  * <p>This example demonstrates how to smoothly report progress in situations where some of the work is optional.</p>
83  *
84  * <pre>
85  *      void doSomething(IProgressMonitor monitor) {
86  *          SubMonitor progress = SubMonitor.convert(monitor, 100);
87  *
88  *          if (condition) {
89  *              // Use 50% of the progress to do some work
90  *              doSomeWork(progress.split(50));
91  *          }
92  *
93  *          // Don't report any work, but ensure that we have 50 ticks remaining on the progress monitor.
94  *          // If we already consumed 50 ticks in the above branch, this is a no-op. Otherwise, the remaining
95  *          // space in the monitor is redistributed into 50 ticks.
96  *
97  *          progress.setWorkRemaining(50);
98  *
99  *          // Use the remainder of the progress monitor to do the rest of the work
100  *          doSomeWork(progress.split(50));
101  *      }
102  * </pre>
103  *
104  * <p>Please beware of the following anti-pattern:</p>
105  *
106  * <pre>
107  *          if (condition) {
108  *              // Use 50% of the progress to do some work
109  *              doSomeWork(progress.split(50));
110  *          } else {
111  *              // Bad: Causes the progress monitor to appear to start at 50%, wasting half of the
112  *              // space in the monitor.
113  *              progress.worked(50);
114  *          }
115  * </pre>
116  *
117  *
118  * <p><b>Example: Loops</b></p>
119  *
120  * <p>This example demonstrates how to report progress in a loop.</p>
121  *
122  * <pre>
123  *      void doSomething(IProgressMonitor monitor, Collection someCollection) {
124  *          SubMonitor progress = SubMonitor.convert(monitor, 100);
125  *
126  *          // Create a new progress monitor that uses 70% of the total progress and will allocate one tick
127  *          // for each element of the given collection.
128  *          SubMonitor loopProgress = progress.split(70).setWorkRemaining(someCollection.size());
129  *
130  *          for (Iterator iter = someCollection.iterator(); iter.hasNext();) {
131  *              Object next = iter.next();
132  *
133  *              doWorkOnElement(next, loopProgress.split(1));
134  *          }
135  *
136  *          // Use the remaining 30% of the progress monitor to do some work outside the loop
137  *          doSomeWork(progress.split(30));
138  *      }
139  * </pre>
140  *
141  *
142  * <p><b>Example: Infinite progress</b></p>
143  *
144  * <p>This example demonstrates how to report logarithmic progress in situations where the number of ticks
145  * cannot be easily computed in advance.</p>
146  *
147  * <pre>
148  *      void doSomething(IProgressMonitor monitor, LinkedListNode node) {
149  *          SubMonitor progress = SubMonitor.convert(monitor);
150  *
151  *          while (node != null) {
152  *              // Regardless of the amount of progress reported so far,
153  *              // use 0.01% of the space remaining in the monitor to process the next node.
154  *              progress.setWorkRemaining(10000);
155  *
156  *              doWorkOnElement(node, progress.split(1));
157  *
158  *              node = node.next;
159  *          }
160  *      }
161  * </pre>
162  *
163  * <p>
164  * This class can be used without OSGi running.
165  * </p>
166  *
167  * @since org.eclipse.equinox.common 3.3
168  */
169 public final class SubMonitor implements IProgressMonitorWithBlocking {
170 
171 	/**
172 	 * Number of trivial split operations (operations which do not report any progress) which can be
173 	 * performed before the monitor performs a cancellation check. This ensures that cancellation
174 	 * checks do not create a performance problem in tight loops that create a lot of SubMonitors,
175 	 * while still ensuring that cancellation is checked occasionally in such loops. This only
176 	 * affects operations which are too small to report any progress. Operations which are large
177 	 * enough to consume at least one tick will always be checked for cancellation.
178 	 */
179 	private static final int TRIVIAL_SPLITS_BEFORE_CANCELLATION_CHECK = 20;
180 
181 	/**
182 	 * The limit for {@link RootInfo#cancellationCheckCounter} before performing a cancellation check.
183 	 */
184 	private static final int TRIVIAL_OPERATION_COUNT_LIMIT = TRIVIAL_SPLITS_BEFORE_CANCELLATION_CHECK;
185 
186 	/**
187 	 * Amount to increment {@link RootInfo#cancellationCheckCounter} when performing
188 	 * a trivial {@link #split(int)} operation.
189 	 */
190 	private static final int TRIVIAL_SPLIT_DELTA = 1;
191 
192 	/**
193 	 * Minimum number of ticks to allocate when calling beginTask on an unknown IProgressMonitor.
194 	 * Pick a number that is big enough such that, no matter where progress is being displayed,
195 	 * the user would be unlikely to notice if progress were to be reported with higher accuracy.
196 	 */
197 	private static final int MINIMUM_RESOLUTION = 1000;
198 
199 	/**
200 	 * The RootInfo holds information about the root progress monitor. A SubMonitor and
201 	 * its active descendants share the same RootInfo.
202 	 */
203 	private static final class RootInfo {
204 		final IProgressMonitor root;
205 
206 		/**
207 		 * Remembers the last task name. Prevents us from setting the same task name multiple
208 		 * times in a row.
209 		 */
210 		String taskName;
211 
212 		/**
213 		 * Remembers the last subtask name. Prevents the SubMonitor from setting the same
214 		 * subtask string more than once in a row.
215 		 */
216 		String subTask;
217 
218 		/**
219 		 * Counter that indicates when we should perform an cancellation check for a trivial
220 		 * operation.
221 		 */
222 		int cancellationCheckCounter;
223 
224 		/**
225 		 * Creates a RootInfo structure that delegates to the given progress monitor.
226 		 *
227 		 * @param root progress monitor to delegate to
228 		 */
RootInfo(IProgressMonitor root)229 		public RootInfo(IProgressMonitor root) {
230 			this.root = root;
231 		}
232 
isCanceled()233 		public boolean isCanceled() {
234 			return root.isCanceled();
235 		}
236 
setCanceled(boolean value)237 		public void setCanceled(boolean value) {
238 			root.setCanceled(value);
239 		}
240 
setTaskName(String taskName)241 		public void setTaskName(String taskName) {
242 			if (eq(taskName, this.taskName)) {
243 				return;
244 			}
245 			this.taskName = taskName;
246 			root.setTaskName(taskName);
247 		}
248 
subTask(String name)249 		public void subTask(String name) {
250 			if (eq(subTask, name)) {
251 				return;
252 			}
253 
254 			this.subTask = name;
255 			root.subTask(name);
256 		}
257 
worked(int i)258 		public void worked(int i) {
259 			root.worked(i);
260 		}
261 
clearBlocked()262 		public void clearBlocked() {
263 			if (root instanceof IProgressMonitorWithBlocking)
264 				((IProgressMonitorWithBlocking) root).clearBlocked();
265 		}
266 
setBlocked(IStatus reason)267 		public void setBlocked(IStatus reason) {
268 			if (root instanceof IProgressMonitorWithBlocking)
269 				((IProgressMonitorWithBlocking) root).setBlocked(reason);
270 		}
271 
checkForCancellation()272 		public void checkForCancellation() {
273 			if (root.isCanceled()) {
274 				throw new OperationCanceledException();
275 			}
276 		}
277 
reportTrivialOperation(int cancellationDelta)278 		public void reportTrivialOperation(int cancellationDelta) {
279 			cancellationCheckCounter += cancellationDelta;
280 			// This is a trivial operation. Only perform a cancellation check after the counter expires.
281 			if (cancellationCheckCounter >= TRIVIAL_OPERATION_COUNT_LIMIT) {
282 				cancellationCheckCounter = 0;
283 				checkForCancellation();
284 			}
285 		}
286 	}
287 
288 	/**
289 	 * Total number of ticks that this progress monitor is permitted to consume
290 	 * from the root.
291 	 */
292 	private int totalParent;
293 
294 	/**
295 	 * Number of ticks that this progress monitor has already reported in the root.
296 	 */
297 	private int usedForParent = 0;
298 
299 	/**
300 	 * Number of ticks that have been consumed by this instance's children.
301 	 */
302 	private double usedForChildren = 0.0;
303 
304 	/**
305 	 * Number of ticks allocated for this instance's children. This is the total number
306 	 * of ticks that may be passed into worked(int) or split(int).
307 	 */
308 	private int totalForChildren;
309 
310 	/**
311 	 * Children created by split will be completed automatically the next time
312 	 * the parent progress monitor is touched. This points to the last incomplete child
313 	 * created with split.
314 	 */
315 	private SubMonitor lastSubMonitor;
316 
317 	/**
318 	 * Used to communicate with the root of this progress monitor tree
319 	 */
320 	private final RootInfo root;
321 
322 	/**
323 	 * A bitwise combination of the SUPPRESS_* flags.
324 	 */
325 	private final int flags;
326 
327 	/**
328 	 * True iff beginTask has been called on the public interface yet.
329 	 */
330 	private boolean beginTaskCalled;
331 
332 	/**
333 	 * True iff ticks have been allocated yet.
334 	 */
335 	private boolean ticksAllocated;
336 
337 	/**
338 	 * May be passed as a flag to {@link #split}. Indicates that the calls
339 	 * to subTask on the child should be ignored. Without this flag,
340 	 * calling subTask on the child will result in a call to subTask
341 	 * on its parent.
342 	 */
343 	public static final int SUPPRESS_SUBTASK = 0x0001;
344 
345 	/**
346 	 * May be passed as a flag to {@link #split}. Indicates that strings
347 	 * passed into beginTask should be ignored. If this flag is
348 	 * specified, then the progress monitor instance will accept null
349 	 * as the first argument to beginTask. Without this flag, any
350 	 * string passed to beginTask will result in a call to
351 	 * setTaskName on the parent.
352 	 */
353 	public static final int SUPPRESS_BEGINTASK = 0x0002;
354 
355 	/**
356 	 * May be passed as a flag to {@link #split}. Indicates that strings
357 	 * passed into setTaskName should be ignored. If this string
358 	 * is omitted, then a call to setTaskName on the child will
359 	 * result in a call to setTaskName on the parent.
360 	 */
361 	public static final int SUPPRESS_SETTASKNAME = 0x0004;
362 
363 	/**
364 	 * May be passed as a flag to {@link #split}. Indicates that isCanceled
365 	 * should always return false.
366 	 * @since 3.8
367 	 */
368 	public static final int SUPPRESS_ISCANCELED = 0x0008;
369 
370 	/**
371 	 * May be passed as a flag to {@link #split}. Indicates that strings
372 	 * passed to setTaskName, subTask, and beginTask should all be ignored.
373 	 */
374 	public static final int SUPPRESS_ALL_LABELS = SUPPRESS_SETTASKNAME | SUPPRESS_BEGINTASK | SUPPRESS_SUBTASK;
375 
376 	/**
377 	 * May be passed as a flag to {@link #split}. Indicates that strings
378 	 * passed to setTaskName, subTask, and beginTask should all be propagated
379 	 * to the parent.
380 	 */
381 	public static final int SUPPRESS_NONE = 0;
382 
383 	/**
384 	 * Bitwise combination of all flags which may be passed in to the public interface on {@link #split}
385 	 */
386 	private static final int ALL_PUBLIC_FLAGS = SUPPRESS_ALL_LABELS | SUPPRESS_ISCANCELED;
387 
388 	/**
389 	 * Bitwise combination of all flags which are inherited directly from a parent SubMonitor to its immediate
390 	 * children. All other flags are either not inherited or are inherited from more complicated logic in {@link #split}
391 	 */
392 	private static final int ALL_INHERITED_FLAGS = SUPPRESS_SUBTASK | SUPPRESS_ISCANCELED;
393 
394 	private static final Set<String> knownBuggyMethods = new HashSet<>();
395 
396 	/**
397 	 * Creates a new SubMonitor that will report its progress via
398 	 * the given RootInfo.
399 	 * @param rootInfo the root of this progress monitor tree
400 	 * @param totalWork total work to perform on the given progress monitor
401 	 * @param availableToChildren number of ticks allocated for this instance's children
402 	 * @param flags a bitwise combination of the SUPPRESS_* constants
403 	 */
SubMonitor(RootInfo rootInfo, int totalWork, int availableToChildren, int flags)404 	private SubMonitor(RootInfo rootInfo, int totalWork, int availableToChildren, int flags) {
405 		root = rootInfo;
406 		totalParent = (totalWork > 0) ? totalWork : 0;
407 		this.totalForChildren = availableToChildren;
408 		this.flags = flags;
409 		ticksAllocated = availableToChildren > 0;
410 	}
411 
412 	/**
413 	 * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is
414 	 * not necessary to call done() on the result, but the caller is responsible for calling
415 	 * done() on the argument. Calls beginTask on the argument.</p>
416 	 *
417 	 * <p>This method should generally be called at the beginning of a method that accepts
418 	 * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
419 	 *
420 	 * <p>Since it is illegal to call beginTask on the same IProgressMonitor more than once,
421 	 * the same instance of IProgressMonitor must not be passed to convert more than once.</p>
422 	 *
423 	 * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
424 	 * as a new instance of <code>NullProgressMonitor</code>.
425 	 * @return a SubMonitor instance that adapts the argument
426 	 */
convert(IProgressMonitor monitor)427 	public static SubMonitor convert(IProgressMonitor monitor) {
428 		return convert(monitor, "", 0); //$NON-NLS-1$
429 	}
430 
431 	/**
432 	 * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
433 	 * with the given number of ticks. It is not necessary to call done() on the result,
434 	 * but the caller is responsible for calling done() on the argument. Calls beginTask
435 	 * on the argument.</p>
436 	 *
437 	 * <p>This method should generally be called at the beginning of a method that accepts
438 	 * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
439 	 *
440 	 * <p>Since it is illegal to call beginTask on the same IProgressMonitor more than once,
441 	 * the same instance of IProgressMonitor must not be passed to convert more than once.</p>
442 	 *
443 	 * @param monitor monitor to convert to a SubMonitor instance or null. Treats null
444 	 * as a new instance of <code>NullProgressMonitor</code>.
445 	 * @param work number of ticks that will be available in the resulting monitor
446 	 * @return a SubMonitor instance that adapts the argument
447 	 */
convert(IProgressMonitor monitor, int work)448 	public static SubMonitor convert(IProgressMonitor monitor, int work) {
449 		return convert(monitor, "", work); //$NON-NLS-1$
450 	}
451 
452 	/**
453 	 * <p>Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
454 	 * with the given number of ticks. It is not necessary to call done() on the result,
455 	 * but the caller is responsible for calling done() on the argument. Calls beginTask
456 	 * on the argument.</p>
457 	 *
458 	 * <p>This method should generally be called at the beginning of a method that accepts
459 	 * an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.</p>
460 	 *
461 	 * <p>Since it is illegal to call beginTask on the same IProgressMonitor more than once,
462 	 * the same instance of IProgressMonitor must not be passed to convert more than once.</p>
463 	 *
464 	 * @param monitor to convert into a SubMonitor instance or null. If given a null argument,
465 	 * the resulting SubMonitor will not report its progress anywhere.
466 	 * @param taskName user readable name to pass to monitor.beginTask. Never null.
467 	 * @param work initial number of ticks to allocate for children of the SubMonitor
468 	 * @return a new SubMonitor instance that is a child of the given monitor
469 	 */
convert(IProgressMonitor monitor, String taskName, int work)470 	public static SubMonitor convert(IProgressMonitor monitor, String taskName, int work) {
471 		if (monitor == null) {
472 			monitor = new NullProgressMonitor();
473 			return new SubMonitor(new RootInfo(monitor), 0, work, SUPPRESS_ALL_LABELS);
474 		}
475 
476 		// Optimization: if the given monitor already a SubMonitor, no conversion is necessary
477 		if (monitor instanceof SubMonitor) {
478 			SubMonitor subMonitor = (SubMonitor) monitor;
479 			subMonitor.beginTaskImpl(taskName, work);
480 			return subMonitor;
481 		}
482 
483 		monitor.beginTask(taskName, MINIMUM_RESOLUTION);
484 		return new SubMonitor(new RootInfo(monitor), MINIMUM_RESOLUTION, work, SUPPRESS_NONE);
485 	}
486 
487 	/**
488 	 * Calls {@link #done()} on the given monitor if is non-null. If the given monitor is null,
489 	 * this is a no-op.
490 	 * <p>
491 	 * This is a convenience method intended to reduce the boilerplate around code which must call
492 	 * {@link #done()} on a possibly-null monitor.
493 	 *
494 	 * @param monitor a progress monitor or null
495 	 * @since 3.8
496 	 */
done(IProgressMonitor monitor)497 	public static void done(IProgressMonitor monitor) {
498 		if (monitor != null) {
499 			monitor.done();
500 		}
501 	}
502 
503 	/**
504 	 * <p>Sets the work remaining for this SubMonitor instance. This is the total number
505 	 * of ticks that may be reported by all subsequent calls to worked(int), split(int), etc.
506 	 * This may be called many times for the same SubMonitor instance. When this method
507 	 * is called, the remaining space on the progress monitor is redistributed into the given
508 	 * number of ticks.</p>
509 	 *
510 	 * <p>It doesn't matter how much progress has already been reported with this SubMonitor
511 	 * instance. If you call setWorkRemaining(100), you will be able to report 100 more ticks of
512 	 * work before the progress meter reaches 100%.</p>
513 	 *
514 	 * @param workRemaining total number of remaining ticks
515 	 * @return the receiver
516 	 */
setWorkRemaining(int workRemaining)517 	public SubMonitor setWorkRemaining(int workRemaining) {
518 		if (TracingOptions.debugProgressMonitors && ticksAllocated && usedForChildren >= totalForChildren && workRemaining > 0) {
519 			logProblem("Attempted to allocate ticks on a SubMonitor which had no space available. " //$NON-NLS-1$
520 					+ "This may indicate that a SubMonitor was reused inappropriately (which is a bug) " //$NON-NLS-1$
521 					+ "or may indicate that the caller was implementing infinite progress and overflowed " //$NON-NLS-1$
522 					+ "(which may not be a bug but may require selecting a higher ratio)"); //$NON-NLS-1$
523 		}
524 
525 		// Ensure we don't try to allocate negative ticks
526 		if (workRemaining > 0) {
527 			ticksAllocated = true;
528 		} else {
529 			workRemaining = 0;
530 		}
531 
532 		// Ensure we don't cause division by zero
533 		if (totalForChildren > 0 && totalParent > usedForParent) {
534 			// Note: We want the following value to remain invariant after this method returns
535 			double remainForParent = totalParent * (1.0d - (usedForChildren / totalForChildren));
536 			usedForChildren = (workRemaining * (1.0d - remainForParent / (totalParent - usedForParent)));
537 		} else
538 			usedForChildren = 0.0d;
539 
540 		totalParent = totalParent - usedForParent;
541 		usedForParent = 0;
542 		totalForChildren = workRemaining;
543 		return this;
544 	}
545 
546 	/**
547 	 * Consumes the given number of child ticks, given as a double. Must only
548 	 * be called if the monitor is in floating-point mode.
549 	 *
550 	 * @param ticks the number of ticks to consume
551 	 * @return ticks the number of ticks to be consumed from parent
552 	 */
consume(double ticks)553 	private int consume(double ticks) {
554 		if (TracingOptions.debugProgressMonitors && !ticksAllocated && ticks > 0) {
555 			logProblem("You must allocate ticks using beginTask or setWorkRemaining before trying to consume them"); //$NON-NLS-1$
556 		}
557 
558 		if (totalParent == 0 || totalForChildren == 0) // this monitor has no available work to report
559 			return 0;
560 
561 		usedForChildren += ticks;
562 
563 		if (usedForChildren > totalForChildren) {
564 			usedForChildren = totalForChildren;
565 			if (TracingOptions.debugProgressMonitors) {
566 				logProblem("This progress monitor consumed more ticks than were allocated for it."); //$NON-NLS-1$
567 			}
568 		} else if (usedForChildren < 0.0)
569 			usedForChildren = 0.0;
570 
571 		int parentPosition = (int) (totalParent * usedForChildren / totalForChildren);
572 		int delta = parentPosition - usedForParent;
573 
574 		usedForParent = parentPosition;
575 		return delta;
576 	}
577 
578 	@Override
isCanceled()579 	public boolean isCanceled() {
580 		if ((flags & SUPPRESS_ISCANCELED) == 0) {
581 			return root.isCanceled();
582 		}
583 		return false;
584 	}
585 
586 	/**
587 	 * Checks whether cancellation of current operation has been requested and throws
588 	 * an {@link OperationCanceledException} if it was the case. This method is a shorthand
589 	 * for:
590 	 * <pre>
591 	 * if (monitor.isCanceled())
592 	 *     throw new OperationCanceledException();
593 	 * </pre>
594 	 *
595 	 * @return this SubMonitor to allow for chained invocation
596 	 * @throws OperationCanceledException if cancellation has been requested
597 	 * @see #isCanceled()
598 	 * @since 3.9
599 	 */
checkCanceled()600 	public SubMonitor checkCanceled() throws OperationCanceledException {
601 		if (isCanceled()) {
602 			throw new OperationCanceledException();
603 		}
604 		return this;
605 	}
606 
607 	@Override
setTaskName(String name)608 	public void setTaskName(String name) {
609 		if ((flags & SUPPRESS_SETTASKNAME) == 0)
610 			root.setTaskName(name);
611 	}
612 
613 	/**
614 	 * Starts a new main task. The string argument is ignored
615 	 * if and only if the SUPPRESS_BEGINTASK flag has been set on this SubMonitor
616 	 * instance.
617 	 *
618 	 * <p>This method is equivalent calling setWorkRemaining(...) on the receiver. Unless
619 	 * the SUPPRESS_BEGINTASK flag is set, this will also be equivalent to calling
620 	 * setTaskName(...) on the parent.</p>
621 	 *
622 	 * @param name new main task name
623 	 * @param totalWork number of ticks to allocate
624 	 *
625 	 * @see org.eclipse.core.runtime.IProgressMonitor#beginTask(java.lang.String, int)
626 	 */
627 	@Override
beginTask(String name, int totalWork)628 	public void beginTask(String name, int totalWork) {
629 		if (TracingOptions.debugProgressMonitors && beginTaskCalled) {
630 			logProblem("beginTask was called on this instance more than once"); //$NON-NLS-1$
631 		}
632 		beginTaskImpl(name, totalWork);
633 	}
634 
beginTaskImpl(String name, int totalWork)635 	private void beginTaskImpl(String name, int totalWork) {
636 		if ((flags & SUPPRESS_BEGINTASK) == 0 && name != null)
637 			root.setTaskName(name);
638 		setWorkRemaining(totalWork);
639 		beginTaskCalled = true;
640 	}
641 
642 	@Override
done()643 	public void done() {
644 		cleanupActiveChild();
645 		int delta = totalParent - usedForParent;
646 		if (delta > 0)
647 			root.worked(delta);
648 
649 		totalParent = 0;
650 		usedForParent = 0;
651 		totalForChildren = 0;
652 		usedForChildren = 0.0d;
653 	}
654 
655 	@Override
internalWorked(double work)656 	public void internalWorked(double work) {
657 		cleanupActiveChild();
658 
659 		int delta = consume((work > 0.0d) ? work : 0.0d);
660 		if (delta != 0)
661 			root.worked(delta);
662 	}
663 
664 	@Override
subTask(String name)665 	public void subTask(String name) {
666 		if ((flags & SUPPRESS_SUBTASK) == 0)
667 			root.subTask(name);
668 	}
669 
670 	@Override
worked(int work)671 	public void worked(int work) {
672 		if (TracingOptions.debugProgressMonitors && work == 0) {
673 			logProblem("Attempted to report 0 ticks of work"); //$NON-NLS-1$
674 		}
675 
676 		internalWorked(work);
677 	}
678 
679 	@Override
setCanceled(boolean b)680 	public void setCanceled(boolean b) {
681 		root.setCanceled(b);
682 	}
683 
684 	/**
685 	 * <p>Creates a new SubMonitor that will consume the given number of ticks from its parent.
686 	 * Shorthand for calling {@link #newChild(int, int)} with (totalWork, SUPPRESS_BEGINTASK).
687 	 *
688 	 * <p>This is much like {@link #split(int)} but it does not check for cancellation and will not
689 	 * throw {@link OperationCanceledException}. New code should consider using {@link #split(int)}
690 	 * to benefit from automatic cancellation checks.
691 	 *
692 	 * @param totalWork number of ticks to consume from the receiver
693 	 * @return new sub progress monitor that may be used in place of a new SubMonitor
694 	 */
newChild(int totalWork)695 	public SubMonitor newChild(int totalWork) {
696 		return newChild(totalWork, SUPPRESS_BEGINTASK);
697 	}
698 
699 	/**
700 	 * <p>This is much like {@link #split}, but it does not check for cancellation and will not
701 	 * throw {@link OperationCanceledException}. New code should consider using {@link #split}
702 	 * to benefit from automatic cancellation checks.
703 	 *
704 	 * <p>Creates a sub progress monitor that will consume the given number of ticks from the
705 	 * receiver. It is not necessary to call <code>beginTask</code> or <code>done</code> on the
706 	 * result. However, the resulting progress monitor will not report any work after the first
707 	 * call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
708 	 * or setWorkRemaining.</p>
709 	 *
710 	 * <p>Each SubMonitor only has one active child at a time. Each time newChild() is called, the
711 	 * result becomes the new active child and any unused progress from the previously-active child is
712 	 * consumed.</p>
713 	 *
714 	 * <p>This is property makes it unnecessary to call done() on a SubMonitor instance, since child
715 	 * monitors are automatically cleaned up the next time the parent is touched.</p>
716 	 *
717 	 * <pre> <code>
718 	 *      ////////////////////////////////////////////////////////////////////////////
719 	 *      // Example 1: Typical usage of newChild
720 	 *      void myMethod(IProgressMonitor parent) {
721 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
722 	 *          doSomething(progress.newChild(50));
723 	 *          doSomethingElse(progress.newChild(50));
724 	 *      }
725 	 *
726 	 *      ////////////////////////////////////////////////////////////////////////////
727 	 *      // Example 2: Demonstrates the function of active children. Creating children
728 	 *      // is sufficient to smoothly report progress, even if worked(...) and done()
729 	 *      // are never called.
730 	 *      void myMethod(IProgressMonitor parent) {
731 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
732 	 *
733 	 *          for (int i = 0; i &lt; 100; i++) {
734 	 *              // Creating the next child monitor will clean up the previous one,
735 	 *              // causing progress to be reported smoothly even if we don't do anything
736 	 *              // with the monitors we create
737 	 *          	progress.newChild(1);
738 	 *          }
739 	 *      }
740 	 *
741 	 *      ////////////////////////////////////////////////////////////////////////////
742 	 *      // Example 3: Demonstrates a common anti-pattern
743 	 *      void wrongMethod(IProgressMonitor parent) {
744 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
745 	 *
746 	 *          // WRONG WAY: Won't have the intended effect, as only one of these progress
747 	 *          // monitors may be active at a time and the other will report no progress.
748 	 *          callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
749 	 *      }
750 	 *
751 	 *      void rightMethod(IProgressMonitor parent) {
752 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
753 	 *
754 	 *          // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
755 	 *          Object someValue = computeValue(progress.newChild(50));
756 	 *          callMethod(progress.newChild(50), someValue);
757 	 *      }
758 	 * </code></pre>
759 	 *
760 	 * @param totalWork number of ticks to consume from the receiver
761 	 * @param suppressFlags a bitwise combination of SUPPRESS_* flags. They can be used to suppress
762 	 * various behaviors on the newly-created monitor. Callers should generally include
763 	 * the {@link #SUPPRESS_BEGINTASK} flag unless they are invoking a method whose JavaDoc specifically
764 	 * states that the string argument to {@link #beginTask(String, int)} must be preserved.
765 	 * @return new sub progress monitor that may be used in place of a new SubMonitor
766 	 */
newChild(int totalWork, int suppressFlags)767 	public SubMonitor newChild(int totalWork, int suppressFlags) {
768 		double totalWorkDouble = (totalWork > 0) ? totalWork : 0.0d;
769 		totalWorkDouble = Math.min(totalWorkDouble, totalForChildren - usedForChildren);
770 		SubMonitor oldActiveChild = lastSubMonitor;
771 		cleanupActiveChild();
772 
773 		// Compute the flags for the child. We want the net effect to be as though the child is
774 		// delegating to its parent, even though it is actually talking directly to the root.
775 		// This means that we need to compute the flags such that - even if a label isn't
776 		// suppressed by the child - if that same label would have been suppressed when the
777 		// child delegated to its parent, the child must explicitly suppress the label.
778 		int childFlags = flags & ALL_INHERITED_FLAGS;
779 
780 		if ((flags & SUPPRESS_SETTASKNAME) != 0) {
781 			// If the parent was ignoring labels passed to setTaskName, then the child will ignore
782 			// labels passed to either beginTask or setTaskName - since both delegate to setTaskName
783 			// on the parent
784 			childFlags |= SUPPRESS_SETTASKNAME | SUPPRESS_BEGINTASK;
785 		}
786 
787 		// Note: the SUPPRESS_BEGINTASK flag does not affect the child since there
788 		// is no method on the child that would delegate to beginTask on the parent.
789 		childFlags |= (suppressFlags & ALL_PUBLIC_FLAGS);
790 
791 		int consumed = consume(totalWorkDouble);
792 
793 		if (TracingOptions.debugProgressMonitors) {
794 			if (totalWork == 0) {
795 				logProblem("Attempted to create a child without providing it with any ticks"); //$NON-NLS-1$
796 			}
797 		} else {
798 			// Only perform optimizations which reuse monitors if we're not debugging progress monitors,
799 			// since reusing the monitors prevents us from tracking the usage of an individual monitor
800 			// in any meaningful way.
801 
802 			// If we're creating a new child that can't report any ticks and we just consumed a previous
803 			// child, just reuse the previous child.
804 			if (consumed == 0 && oldActiveChild != null && childFlags == oldActiveChild.flags) {
805 				lastSubMonitor = oldActiveChild;
806 				return oldActiveChild;
807 			}
808 
809 			// If the new child is going to consume the entire parent, return the parent itself.
810 			if (usedForParent >= totalParent && childFlags == flags) {
811 				totalParent = consumed;
812 				usedForParent = 0;
813 				totalForChildren = 0;
814 				usedForChildren = 0;
815 				return this;
816 			}
817 		}
818 
819 		SubMonitor result = new SubMonitor(root, consumed, 0, childFlags);
820 		lastSubMonitor = result;
821 		return result;
822 	}
823 
824 	/**
825 	 * This is shorthand for calling <code>split(totalWork, SUPPRESS_BEGINTASK)</code>. See
826 	 * {@link #split(int, int)} for more details.
827 	 *
828 	 * <p>Creates a sub progress monitor that will consume the given number of ticks from the
829 	 * receiver. It is not necessary to call <code>beginTask</code> or <code>done</code> on the
830 	 * result. However, the resulting progress monitor will not report any work after the first
831 	 * call to done() or before ticks are allocated. Ticks may be allocated by calling {@link #beginTask}
832 	 * or {@link #setWorkRemaining}.</p>
833 	 *
834 	 * <p>This method is much like {@link #newChild}, but it will additionally check for cancellation and
835 	 * will throw an OperationCanceledException if the monitor has been cancelled. Not every call to
836 	 * this method will trigger a cancellation check. The checks will be performed as often as possible
837 	 * without degrading the performance of the caller.
838 	 *
839 	 * <p>Each SubMonitor only has one active child at a time. Each time {@link #newChild} or
840 	 * {@link #split} is called, the result becomes the new active child and any unused progress
841 	 * from the previously-active child is consumed.</p>
842 	 *
843 	 * <p>This makes it unnecessary to call done() on a SubMonitor instance, since child
844 	 * monitors are automatically cleaned up the next time the parent is touched.</p>
845 	 *
846 	 * <pre><code>
847 	 *      ////////////////////////////////////////////////////////////////////////////
848 	 *      // Example 1: Typical usage of split
849 	 *      void myMethod(IProgressMonitor parent) {
850 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
851 	 *          doSomething(progress.split(50));
852 	 *          doSomethingElse(progress.split(50));
853 	 *      }
854 	 *
855 	 *      ////////////////////////////////////////////////////////////////////////////
856 	 *      // Example 2: Demonstrates the function of active children. Creating children
857 	 *      // is sufficient to smoothly report progress, even if worked(...) and done()
858 	 *      // are never called.
859 	 *      void myMethod(IProgressMonitor parent) {
860 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
861 	 *
862 	 *          for (int i = 0; i &lt; 100; i++) {
863 	 *              // Creating the next child monitor will clean up the previous one,
864 	 *              // causing progress to be reported smoothly even if we don't do anything
865 	 *              // with the monitors we create
866 	 *          	progress.split(1);
867 	 *          }
868 	 *      }
869 	 *
870 	 *      ////////////////////////////////////////////////////////////////////////////
871 	 *      // Example 3: Demonstrates a common anti-pattern
872 	 *      void wrongMethod(IProgressMonitor parent) {
873 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
874 	 *
875 	 *          // WRONG WAY: Won't have the intended effect, as only one of these progress
876 	 *          // monitors may be active at a time and the other will report no progress.
877 	 *          callMethod(progress.split(50), computeValue(progress.split(50)));
878 	 *      }
879 	 *
880 	 *      void rightMethod(IProgressMonitor parent) {
881 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
882 	 *
883 	 *          // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
884 	 *          Object someValue = computeValue(progress.split(50));
885 	 *          callMethod(progress.split(50), someValue);
886 	 *      }
887 	 * </code></pre>
888 	 *
889 	 * @param totalWork number of ticks to consume from the receiver
890 	 * @return a new SubMonitor instance
891 	 * @throws OperationCanceledException if the monitor has been cancelled
892 	 * @since 3.8
893 	 */
split(int totalWork)894 	public SubMonitor split(int totalWork) throws OperationCanceledException {
895 		return split(totalWork, SUPPRESS_BEGINTASK);
896 	}
897 
898 	/**
899 	 * <p>Creates a sub progress monitor that will consume the given number of ticks from the
900 	 * receiver. It is not necessary to call <code>beginTask</code> or <code>done</code> on the
901 	 * result. However, the resulting progress monitor will not report any work after the first
902 	 * call to done() or before ticks are allocated. Ticks may be allocated by calling {@link #beginTask}
903 	 * or {@link #setWorkRemaining}</p>
904 	 *
905 	 * <p>This method is much like {@link #newChild}, but will additionally check for cancellation and
906 	 * will throw an {@link OperationCanceledException} if the monitor has been cancelled. Not every call to
907 	 * this method will trigger a cancellation check. The checks will be performed as often as possible
908 	 * without degrading the performance of the caller.
909 	 *
910 	 * <p>Each SubMonitor only has one active child at a time. Each time {@link #newChild} or
911 	 * {@link #split} is called, the result becomes the new active child and any unused progress
912 	 * from the previously-active child is consumed.</p>
913 	 *
914 	 * <p>This is property makes it unnecessary to call done() on a SubMonitor instance, since child
915 	 * monitors are automatically cleaned up the next time the parent is touched.</p>
916 	 *
917 	 * <pre> <code>
918 	 *      ////////////////////////////////////////////////////////////////////////////
919 	 *      // Example 1: Typical usage of split
920 	 *      void myMethod(IProgressMonitor parent) {
921 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
922 	 *          doSomething(progress.split(50));
923 	 *          doSomethingElse(progress.split(50));
924 	 *      }
925 	 *
926 	 *      ////////////////////////////////////////////////////////////////////////////
927 	 *      // Example 2: Demonstrates the function of active children. Creating children
928 	 *      // is sufficient to smoothly report progress, even if worked(...) and done()
929 	 *      // are never called.
930 	 *      void myMethod(IProgressMonitor parent) {
931 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
932 	 *
933 	 *          for (int i = 0; i &lt; 100; i++) {
934 	 *              // Creating the next child monitor will clean up the previous one,
935 	 *              // causing progress to be reported smoothly even if we don't do anything
936 	 *              // with the monitors we create
937 	 *          	progress.split(1);
938 	 *          }
939 	 *      }
940 	 *
941 	 *      ////////////////////////////////////////////////////////////////////////////
942 	 *      // Example 3: Demonstrates a common anti-pattern
943 	 *      void wrongMethod(IProgressMonitor parent) {
944 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
945 	 *
946 	 *          // WRONG WAY: Won't have the intended effect, as only one of these progress
947 	 *          // monitors may be active at a time and the other will report no progress.
948 	 *          callMethod(progress.split(50), computeValue(progress.split(50)));
949 	 *      }
950 	 *
951 	 *      void rightMethod(IProgressMonitor parent) {
952 	 *          SubMonitor progress = SubMonitor.convert(parent, 100);
953 	 *
954 	 *          // RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
955 	 *          Object someValue = computeValue(progress.split(50));
956 	 *          callMethod(progress.split(50), someValue);
957 	 *      }
958 	 * </code></pre>
959 	 *
960 	 * @param totalWork number of ticks to consume from the receiver
961 	 * @param suppressFlags a bitwise combination of SUPPRESS_* flags. They can be used to suppress
962 	 * various behaviors on the newly-created monitor. Callers should generally include
963 	 * the {@link #SUPPRESS_BEGINTASK} flag unless they are invoking a method whose JavaDoc specifically
964 	 * states that the string argument to {@link #beginTask(String, int)} must be preserved.
965 	 * @return new sub progress monitor that may be used in place of a new SubMonitor
966 	 * @throws OperationCanceledException if the monitor has been cancelled
967 	 * @since 3.8
968 	 */
split(int totalWork, int suppressFlags)969 	public SubMonitor split(int totalWork, int suppressFlags) throws OperationCanceledException {
970 		int oldUsedForParent = this.usedForParent;
971 		SubMonitor result = newChild(totalWork, suppressFlags);
972 
973 		if ((result.flags & SUPPRESS_ISCANCELED) == 0) {
974 			int ticksTheChildWillReportToParent = result.totalParent;
975 
976 			// If the new child reports a nonzero amount of progress.
977 			if (ticksTheChildWillReportToParent > 0) {
978 				// Don't check for cancellation if the child is consuming 100% of its parent since whatever code created
979 				// the parent already performed this check.
980 				if (oldUsedForParent > 0 || usedForParent < totalParent) {
981 					// Treat this as a nontrivial operation and check for cancellation unconditionally.
982 					root.checkForCancellation();
983 				}
984 			} else {
985 				root.reportTrivialOperation(TRIVIAL_SPLIT_DELTA);
986 			}
987 		}
988 		return result;
989 	}
990 
cleanupActiveChild()991 	private void cleanupActiveChild() {
992 		IProgressMonitor child = lastSubMonitor;
993 		if (child == null) {
994 			return;
995 		}
996 
997 		lastSubMonitor = null;
998 		child.done();
999 	}
1000 
1001 	@Override
clearBlocked()1002 	public void clearBlocked() {
1003 		root.clearBlocked();
1004 	}
1005 
1006 	@Override
setBlocked(IStatus reason)1007 	public void setBlocked(IStatus reason) {
1008 		root.setBlocked(reason);
1009 	}
1010 
eq(Object o1, Object o2)1011 	protected static boolean eq(Object o1, Object o2) {
1012 		if (o1 == null)
1013 			return (o2 == null);
1014 		if (o2 == null)
1015 			return false;
1016 		return o1.equals(o2);
1017 	}
1018 
getCallerName()1019 	private static String getCallerName() {
1020 		StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
1021 
1022 		String ourClassName = SubMonitor.class.getCanonicalName();
1023 		for (int idx = 1; idx < stackTrace.length; idx++) {
1024 			String className = stackTrace[idx].getClassName();
1025 			if (className.equals(ourClassName)) {
1026 				continue;
1027 			}
1028 
1029 			return stackTrace[idx].toString();
1030 		}
1031 
1032 		return "Unknown"; //$NON-NLS-1$
1033 	}
1034 
logProblem(String message)1035 	private static void logProblem(String message) {
1036 		String caller = getCallerName();
1037 		synchronized (knownBuggyMethods) {
1038 			if (!knownBuggyMethods.add(caller)) {
1039 				return;
1040 			}
1041 		}
1042 		RuntimeLog.log(new Status(IStatus.WARNING, "org.eclipse.core.runtime", message, new Throwable())); //$NON-NLS-1$
1043 	}
1044 
1045 	@Override
toString()1046 	public String toString() {
1047 		return "SubMonitor [totalParent=" + totalParent + ", usedForParent=" + usedForParent + ", usedForChildren=" + usedForChildren + ", totalForChildren=" + totalForChildren + ", beginTaskCalled=" + beginTaskCalled + "]";
1048 	}
1049 
1050 }
1051