Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Article-Progress-Monitors/article.html')
-rw-r--r--Article-Progress-Monitors/article.html948
1 files changed, 571 insertions, 377 deletions
diff --git a/Article-Progress-Monitors/article.html b/Article-Progress-Monitors/article.html
index 805e39a..4b31cdc 100644
--- a/Article-Progress-Monitors/article.html
+++ b/Article-Progress-Monitors/article.html
@@ -1,433 +1,627 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
-<head>
-
-
-
+<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-
-
-
-
-
- <title>How to Correctly and Uniformly Use Progress Monitors</title>
+ <title>Using Progress Monitors</title>
<link rel="stylesheet" href="../default_style.css">
</head>
-
<body link="#0000ff" vlink="#800080">
-
-
<div align="right">&nbsp; <font face="Times New Roman, Times, serif" size="2">Copyright
- &copy; 2006 Kenneth &Ouml;lwing</font>
+ &copy; 2016 Stefan Xenos and others</font>
<table border="0" cellpadding="2" cellspacing="0" width="100%">
-
-
<tbody>
-
<tr>
-
-
<td colspan="2" align="left" bgcolor="#0080c0" valign="top"><b><font face="Arial,Helvetica"><font color="#ffffff">&nbsp;Eclipse
Corner Article</font></font></b></td>
-
-
</tr>
-
-
-
-
</tbody>
</table>
-
-
</div>
-
-
<div align="left">
-
<h1><img src="images/Idea.jpg" align="middle" height="86" width="120"></h1>
-
-
</div>
-
-
<p>&nbsp;</p>
-
-
-
-<h1 align="center">How to Correctly and Uniformly Use Progress Monitors</h1>
-
-
-
+<h1 align="center">Using Progress Monitors</h1>
<blockquote>
<b>Summary</b>
<br>
-Handling a progress monitor instance is deceptively simple. It seems to
-be straightforward but it is easy to make a mistake when using them.
-And, depending on numerous factors such as the underlying
-implementation, how it is displayed, if it&rsquo;s set to use a fixed
-number of work items or &lsquo;unknown&rsquo;, if used through a <span style="font-style: italic;">SubProgressMonitor</span> wrapper etc., the result can range from completely ok, mildly confusing or outright silliness. <br>
+In this article I'll explain how to report progress in Eclipse. I'll
+discuss the contract on IProgressMonitor, demonstrate some common patterns
+using SubMonitor, and explain how to migrate legacy code to take advantage
+of the API introduced in Eclipse 4.6.
<br>
-In this article I hope I can lay down a few ground rules that will help
-anyone use progress monitors in a way that will work with the explicit
-and implicit contract of <span style="font-style: italic;">IProgressMonitor</span>. Also, understanding the usage side makes it easier to understand how to implement a monitor.<br>
-
-
- <p><b> By Kenneth &Ouml;lwing, BEA JRPG</b> <br>
-January 18, 2006<font size="-1"></font> </p>
-
+ <p><b> By Stefan Xenos, Google</b> <br>
+April 19, 2016<font size="-1"></font> </p>
</blockquote>
-
-
<hr width="100%">
-<h2>Using a progress monitor - what's up with that?</h2>
-
-It all really comes down to a few, not too complex, rules. A common
-theme is 'know what you know - but only that'. This means that you
-shouldn't assume you know things you really don't know, and this
-includes the common mistake of only considering progress monitors you
-have seen, i.e. typically the graphical ones when using the IDE.
-Another thing to watch out for is the fact that commonly you design a
-number of tasks that may call each other using sub progress monitors,
-and while doing that make assumptions based on your knowledge that they
-will be called in this manner - never forget that sometime maybe your
-separate subtasks may be called from not-yet-written routines. It's
-then vitally important that your subtasks act exactly in a 'neutral'
-manner, i.e. with no 'implicit assumptions' on what happened before or
-what will happen after.<br>
-
-<br>
-
-One of the motivations for this article is when I tried my hand at
-implementing a progress monitor intended for headless/console use - and
-realised that code using it could make it look really wacky when the
-monitor was wrongly used, and this was issues that were not as readily
-apparent with a graphical monitor. Also, code (including my own)
-frequently abuses the explicit and implicit (which admittedly are my
-interpretation of reasonable behavior) contract that the
-IProgressMonitor interface states, and this makes for dicey decisions
-for a monitor implementor - should it complain (and how) when it gets
-conflicting orders? If not, how should it then behave to make for a
-reasonable and intuitive user experience?<br>
-
-<br>
-
-<!-- Anyway, since an article of this type would have helped me immensely
-when I started working in the Eclipse environment, I figured I should
-try my hand at summing up my view of how the interaction with <span style="font-style: italic;">IProgressMonitor</span> should work.<br>-->
-
-<h3>The protocol of <span style="font-style: italic;">IProgressMonitor</span></h3>
-
-Generally, all interaction with a progress monitor is through the interface <span style="font-style: italic;">IProgressMonitor</span>
-and this interface defines the protocol behavior expected. It does
-leave some things up in the air though; for example, the description
-states some things that should be true, but the methods have no <span style="font-style: italic;">throws</span>
-clause that helps enforce some invariants. I have chosen to interpret
-the descriptions &lsquo;hard&rsquo;, even to the point of saying
-it&rsquo;s valid to throw an (unchecked) exception if a described rule
-is violated (this is somewhat controversial of course - if you
-implement a monitor doing this you should probably provide a way to
-turn off 'strictness'). Hopefully we could eventually see a new
-interface that deprecates the old methods and provides new ones that
-better reflect the contract. The discussion below is based on the
-assumption that the reader is familiar with the general API; review it
-in the Eclipse help.<br>
-
-<br>
-
-The first important consideration is the realization that a monitor
-(contract wise) can be in basically four states. Any given
-implementation may or may not track those state changes and may or may
-not do anything about them, which is part of the reason that
-misbehaving users of a monitor sometimes gets away with it. Only one of
-these states are readily testable using the interface however (if the
-monitor is canceled); the other states are just a given from correct
-use of the interface.<br>
-
-<br>
-
-Essentially, the state changes are governed by the methods <span style="font-style: italic;">beginTask()</span>, <span style="font-style: italic;">done()</span> and <span style="font-style: italic;">setCanceled()</span>,
-plus the implicit initial state of a new instance. Note that for the
-purposes discussed here the perceived &lsquo;changes in state&rsquo;
-occurring as a result from calling <span style="font-style: italic;">worked()</span> is not relevant. A separate discussion below details how to deal with <span style="font-style: italic;">worked()</span> calls.<br>
-
-<br>
-
-NB: The states described here are not any &lsquo;officialese&rsquo;
-that can be found as constants or anything like that; they&rsquo;re
-only here to serve so they can be used for discussion.<br>
-
-<br>
-
-<ul>
-
- <li>PRISTINE<br>
-
-This is the initial state of a newly created instance of an <span style="font-style: italic;">IProgressMonitor</span> implementation, i.e. before <span style="font-style: italic;">beginTask()</span>
-has been called. In principle a given implementation may handle a
-single instance such that it is reusable and reverted back to the
-PRISTINE state after a done() call, but that is opaque from the point
-of the contract. In this state it should be essentially correct and
-possible to go to any of the other states, but the typical and expected
-transition should be from PRISTINE to IN_USE as a result from a
-successful beginTask() call. The transition to FINISHED should result
-only in a very particular situation, see more below.</li>
+<h2>1.0 Introduction</h2>
+
+So you're writing a long-running method. It takes an IProgressMonitor as a parameter. You want it to
+report smooth progress, be cancellable from the UI thread and accomplish this with minimal boilerplate.
+Unfortunately, most of the examples you've seen either omit progress reporting entirely or contain
+more boilerplate than code.
+<p>
+Is it possible to get the smooth progress reporting without all that boilerplate? If so, what are the
+responsibilities of your method and what are the responsibilities of its caller? This article should help.
+
+<h2>2.0 Using SubMonitor</h2>
+
+Use SubMonitor. If you remember nothing else from this article, remember that.
+<p>
+SubMonitor is an implementation of IProgressMonitor that simplifies everything related to progress
+reporting. Whenever you write a method that accepts an IProgressMonitor, the first thing you should
+do is convert it to a SubMonitor using <code>SubMonitor.convert(...)</code>.
+
+<h3>2.1 Allocating Ticks</h3>
+<p>
+There are several overloads for <code>convert</code> and most of them accept a number of ticks as an
+argument. These are said to "allocate ticks". A tick is a unit of work to be performed. Allocating
+ticks distributes those ticks across the remaining space of the progress monitor but doesn't
+actually report any progress. It basically sets the denominator that will be used for subsequent
+progress reporting.
+<p>
+How many ticks do you need? Take a look at all the slow things your method does and assign them
+a number of ticks based on how long you think they will take. Any method you call that takes a
+progress monitor should be considered a "slow thing". If you think one thing will take longer
+than another, give it more ticks. If you think it will take twice as long, give it twice as many.
+When you're done, add up all the ticks. That's how many you should allocate. Ticks only have
+meaning relative to other ticks on the same monitor instance: their absolute value doesn't
+mean anything.
+<p>
+There are several methods which allocate ticks. Normally you'll allocate them at construction-time
+using <code>SubMonitor.convert(...)</code> but this only works if you're creating a new
+SubMonitor instance.
+<p>
+Sometimes you'll want to allocate (or reallocate) the ticks on an existing
+monitor in which case you'll want <code>SubMonitor.setWorkRemaining</code>. You can
+call this as often as you like on a SubMonitor instance. When you do, any remaining unconsumed
+space on the monitor is divided into the given number of ticks and any previously-allocated
+ticks are forgotten.
+<p>
+The last method that allocates ticks is called <code>beginTask</code>. It's used as part of the
+progress reporting framework and you rarely need to call it directly. You'll see this used
+a lot in older code and we'll get more into it later. For now, it's best to avoid it in new
+code unless you're implementing your own IProgressMonitor.
+
+<h3>2.2 Consuming Ticks</h3>
+
+Once you've allocated the ticks you can consume them. Consuming ticks is what reports progress.
+Let's say you allocate 50 ticks and then consume 3 of them. That means your progress bar will
+be 3/50 of the way across, or 6%. Note that you must allocate ticks before you can consume them
+on any given progress monitor instance. Attempting to consume ticks without allocating them is an error.
+<p>
+There are several methods on SubMonitor which consume ticks. Namely, <code>split(...)</code>,
+<code>newChild(...)</code>, and <code>worked(...)</code>. Practically speaking the only one you
+need is <code>split(...)</code>.
+<p>
+I'll be using <code>split(...)</code> for most of the code examples in this article, but it is new
+in Eclipse 4.6. If your code is meant to work on earlier versions of Eclipse you should use
+<code>newChild(...)</code> instead of <code>split(...)</code>. The two do pretty much the same
+thing except that <code>split(...)</code> also performs cancellation checks.
+<p>
+
+<h3>2.3 Split</h3>
+
+<code>split(...)</code> doesn't immediately consume the ticks. It uses the ticks to create a new
+child monitor but first it fully consumes any leftover ticks in any previous children
+of the same parent.
+<p>
+I'll demonstrate with an example:
+<pre>
+ void myMethod(IProgressMonitor monitor) {
+ // No ticks have been allocated yet, so we can't consume them.
+ SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
+
+ // monitor is now being managed by subMonitor. We shouldn't use it directly again.
+ // subMonitor has 100 ticks allocated for it and we can start consuming them.
+
+ SubMonitor child1 = subMonitor.split(10);
+
+ // subMonitor now has 90 ticks allocated. 10 of the original 100 were used to build child1.
+ // child1 has no ticks allocated for it yet so we can't consume ticks from it yet.
+
+ child1.setWorkRemaining(100);
+
+ // child1 now has 100 ticks allocated for it. Consuming 1 tick from child1 now would
+ // advance the root monitor by 0.1%.
+
+ SubMonitor grandchild1 = child1.split(50);
+
+ // child1 now has 50 ticks allocated.
+
+ SubMonitor grandchild2 = child1.split(50);
+
+ // Allocating a new grandchild from child1 has caused grandchild1 to be consumed.
+ // Our root progress monitor now shows 5% progress.
+
+ SubMonitor child2 = subMonitor.split(40);
+
+ // Allocating a new child from subMonitor has caused child1 and grandchild2 to be
+ // consumed. Our root progress monitor now shows 10% progress.
+
+ SubMonitor child3 = subMonitor.split(10);
+
+ // Child2 was consumed. The root progress monitor now shows 50% progress.
+
+ SubMonitor child4 = subMonitor.split(40);
+
+ // Child3 was consumed. The root progress monitor now shows 60% progress.
+ }
+</pre>
+
+<h3>2.4 Cancellation</h3>
+
+Long-running methods should check the value of <code>IProgressMonitor.isCanceled()</code>
+periodically. If it returns true, they should terminate cleanly and throw
+<code>OperationCanceledException</code>. In Eclipse 4.5 and earlier, this was done with
+explicit cancellation checks like this:
+
+<pre>
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+</pre>
+
+Unfortunately, these sorts of cancellation checks are cumbersome and can become a
+performance bottleneck if performed too frequently.
+<p>
+In Eclipse 4.6 and on, cancellation checks are be performed implicitly by
+<code>SubMonitor.split(...)</code>. Code should be migrated to use <code>split</code>
+wherever possible and explicit cancellation checks should be deleted.
+<p>
+So how does <code>split</code> work and how does it replace explicit cancellation checks?
+It's basically just a helper that does the same thing as <code>newChild</code> but
+additionally includes a cancellation check. Internally, split does something like this
+(pseudocode):
+
+<pre>
+ SubMonitor split(int ticks) {
+ if (checking_cancelation_now_wouldnt_cause_a_performance_problem()) {
+ if (isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ }
+ return newChild(ticks);
+ }
+</pre>
+
+<h2>3.0 Examples</h2>
+
+Lets look at some examples of common progress reporting patterns.
+
+<h3>3.1 Calling child methods</h3>
+
+Most long-running operation will need to call out to other long-running operations.
+
+<pre>
+ void doSomething(IProgressMonitor monitor) {
+ // Convert the given monitor into a SubMonitor instance. We shouldn't use the original
+ // monitor object again since subMonitor will consume the entire monitor.
+ SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
- <li>IN_USE<br>
+ // Use 30% of the progress to do some work
+ someChildTask(subMonitor.split(30));
-This is the state the monitor after the first and <span style="text-decoration: underline;">only</span> call to <span style="font-style: italic;">beginTask()</span>. This is one of those things that are very easy to get wrong; contract wise, <span style="font-style: italic;">beginTask()</span>
-can and should only be called at most once for a given instance. A more
-detailed discussion on the code pattern required to deal with this
-obligation can be found below.</li>
+ // Use the remaining 70% of the progress to do some more work
+ someChildTask(subMonitor.split(70));
+ }
+</pre>
- <li>FINISHED<br>
+<h3>3.2 Branches</h3>
-The transition to this state is achieved by calling <span style="font-style: italic;">done()</span>. As with <span style="font-style: italic;">beginTask()</span>, <span style="font-style: italic;">done()</span> should only be called <span style="text-decoration: underline;">once</span> and should <span style="text-decoration: underline;">always</span> be called on a monitor when <span style="font-style: italic;">beginTask()</span> has been called (i.e. it is ok to not call <span style="font-style: italic;">done()</span>
-only if the monitor is still in the PRISTINE state). Again, the
-discussion below is more detailed on how to ensure proper protocol.</li>
+Sometimes some long-running piece of code is optional. If the optional piece is skipped, you still want the
+total work to add up to 100%, but you also don't want to waste a portion of the progress monitor just to
+make the ticks line up. One approach is to do the optional part first and then use setWorkRemaining to
+redistribute the remaining ticks.
- <li>CANCELED<br>
-
-Actually, this state is slightly murky; it&rsquo;s possible that
-canceled/not canceled should be tracked separately from the others.
-But, contract wise it should be adequate if this state is either
-achieved directly from PRISTINE and just left that way, or if <span style="font-style: italic;">done()</span> is called (likely as a result of detecting the canceled status), it is cleared and the monitor then transitions to FINISHED.</li>
+<pre>
+ void doSomething(IProgressMonitor monitor) {
+ SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
+
+ if (condition1) {
+ doSomeWork(subMonitor.split(20));
+ }
+
+ // Don't report any work, but ensure that we have 80 ticks remaining on the progress monitor.
+ // If we already consumed ticks in the above branch, this is a no-op. Otherwise, the remaining
+ // space in the monitor is redistributed.
+ subMonitor.setWorkRemaining(80);
+
+ if (condition2) {
+ doMoreWork(subMonitor.split(40));
+ }
+
+ subMonitor.setWorkRemaining(40)
+
+ doSomeMoreWork(subMonitor.split(40));
+ }
+</pre>
+
+This approach works well enough in most cases and requires minimal boilerplate but the progress it reports
+can sometimes be uneven if the method ends with a bunch of conditionals that are often skipped. Another
+approach is to count the number of ticks in advance:
+
+<pre>
+ void doSomething(IProgressMonitor monitor) {
+ int totalTicks = 0;
+ if (condition1) {
+ totalTicks += OPERATION_ONE_TICKS;
+ }
+ if (condition2) {
+ totalTicks += OPERATION_TWO_TICKS;
+ }
+ if (condition3) {
+ totalTicks += OPERATION_THREE_TICKS;
+ }
+ // Allocate a different number of ticks based on which branches we expect to execute.
+ SubMonitor subMonitor = SubMonitor.convert(monitor, totalTicks);
+
+ if (condition1) {
+ doSomeWork(subMonitor.split(OPERATION_ONE_TICKS));
+ }
+ if (condition2) {
+ doSomeWork(subMonitor.split(OPERATION_TWO_TICKS));
+ }
+ if (condition3) {
+ doSomeWork(subMonitor.split(OPERATION_THREE_TICKS));
+ }
+ }
+</pre>
+
+This will usually report smoother progress, but due to the extra complexity it's usually best to only
+use this pattern if otherwise jerkiness of reported progress would be annoying to the user.
+
+<h3>3.3 Loops</h3>
+
+This example demonstrates how to report progress in a loop where every iteration takes roughly
+the same amount of time.</p>
+
+<pre>
+ void doSomething(IProgressMonitor monitor, Collection someCollection) {
+ SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
+
+ // Create a new progress monitor for the loop.
+ SubMonitor loopMonitor = subMonitor.split(70).setWorkRemaining(someCollection.size());
+
+ for (Object next: someCollection) {
+ // Create a progress monitor for each loop iteration.
+ SubMonitor iterationMonitor = loopMonitor.split(1);
+
+ doWorkOnElement(next, iterationMonitor);
+ }
+
+ // The original progress monitor can be used for further work after the loop terminates.
+ doSomeWork(subMonitor.split(30));
+ }
+</pre>
+
+<h3>3.4 Skipping elements in a loop</h3>
+
+Sometimes some elements from a loop will be skipped. In that case, it's better to use the space
+in the progress monitor to report the work done for the long-running elements rather than the
+fast elements.
+
+<pre>
+ void doSomething(IProgressMonitor monitor, Collection someCollection) {
+ SubMonitor loopMonitor = SubMonitor.convert(monitor, someCollection.size());
+
+ int remaining = someCollection.size();
+ for (Object next : someCollection) {
+ loopMonitor.setWorkRemaining(remaining--);
+
+ if (shouldSkip(next)) {
+ continue;
+ }
+
+ // Create a progress monitor for each loop iteration.
+ SubMonitor iterationMonitor = loopMonitor.split(1);
+ doWorkOnElement(next, iterationMonitor);
+ }
+ }
+</pre>
+
+This works well enough if skipped elements are rare but if most of the elements are skipped, this pattern
+will tend to make poor use of the end of the monitor. If many elements might be skipped, it's better to
+pre-filter the list like this:
+
+<pre>
+ void doSomething(IProgressMonitor monitor, Collection someCollection) {
+ List filteredElements = someCollection
+ .stream()
+ .filter(next -> !shouldSkip(next))
+ .collect(Collectors.toList());
+
+ SubMonitor loopMonitor = SubMonitor.convert(monitor, filteredElements.size());
+ for (Object next : filteredElements) {
+ doWorkOnElement(next, loopMonitor.split(1));
+ }
+ }
+</pre>
+
+<h3>3.5 Queues</h3>
+
+What if you're performing a depth-first search or some other algorithm where more work is
+continually discovered as you proceed? Try putting the work-discovered-so-far in a queue
+and using the size of the queue to allocate ticks on your monitor. When using this pattern,
+always make sure you never allocate less than some minimum number of ticks or you'll consume
+the entire progress monitor on the first few iterations of your algorithm.
+
+<pre>
+ void depthFirstSearch(IProgressMonitor monitor, Object root) {
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+ ArrayList queue = new ArrayList();
+ queue.add(root);
+
+ while (!queue.isEmpty()) {
+ // Allocate a number of ticks equal to the size of the queue or some constant,
+ // whatever is larger. This constant prevents the entire monitor from being consumed
+ // at the start when the queue is very small.
+ subMonitor.setWorkRemaining(Math.max(queue.size(), 20));
+ Object next = queue.remove(queue.size() - 1);
+ processElement(next, subMonitor.split(1));
+ queue.addAll(getChildrenFor(next));
+ }
+ }
+</pre>
+
+<h3>3.6 Unknown progress</h3>
+
+What about those situations where you really have no idea how much work to report or how
+long it will take? Try allocating a small percentage of the remaining space on each iteration.
+
+<pre>
+ void unknownProgress(IProgressMonitor monitor) {
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+ while (hasMore()) {
+ // Use 1% of the remaining space for each iteration
+ processNext(subMonitor.setWorkRemaining(100).split(1));
+ }
+ }
+</pre>
+
+Notice the idiom <code>setWorkRemaining(denominator).split(numerator)</code>. This can be used
+at any point to consume numerator/denominator of the remaining space in a monitor.
+
+<h3>3.7 Naming conventions</h3>
+
+In these examples we've used the same naming convention that has been used within
+the Eclipse platform. You may wish to use the same convention to help convey the purpose of your
+progress monitors:
+<ul>
+<li><b>subMonitor</b> - a SubMonitor that tracks the entire progress of the method.</li>
+<li><b>loopMonitor</b> - a SubMonitor that tracks the progress of a single loop. If a method contains
+ multiple loops, this is used as a suffix.</li>
+<li><b>iterationMonitor</b> - a SubMonitor that tracks the progress of a single iteration of a loop.
+ If there are multiple nested loops, this may be used as a suffix.</li>
+<li><b>monitor</b> - an IProgressMonitor that is passed as a method argument.</li>
</ul>
-<br>
-
-Now, one contract pattern described above is that if <span style="font-style: italic;">beginTask()</span> is ever called, <span style="font-style: italic;">done()</span> MUST be called. This is achieved by always following this code pattern (all code is simplified):<br>
+</ul>
-<pre style="margin-left: 40px;">monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>// figure some things out such as number of items to process etc&hellip;<br>try<br> {<br> monitor.beginTask(&hellip;)<br> // do stuff and call worked() for each item worked on, and check for cancellation<br> }<br>finally<br> {<br> monitor.done()<br> } <br></pre>
+<h2>4.0 Responsibilities of callers and callees</h2>
-The important thing here then is to ensure that <span style="font-style: italic;">done()</span> is always called (by virtue of being in the <span style="font-style: italic;">finally</span> clause) but (normally) only if <span style="font-style: italic;">beginTask()</span> has been successfully called (by virtue of being the first thing called in the <span style="font-style: italic;">try</span> clause). There is a small loophole that could cause <span style="font-style: italic;">done()</span>
-to be called without the monitor actually transitioning from PRISTINE
-to IN_USE. This loophole can&nbsp;with this pattern only happen if a
-particular <span style="font-style: italic;">beginTask()</span> implementation throws an unchecked exception (The interface itself declares no <span style="font-style: italic;">throws</span>
-clause) before it internally makes a note of the state change (if the
-specific implementation even tracks state in this manner and/or is too
-loose in its treatment of the interface contract).<br>
-<br>
-<img style="width: 62px; height: 13px;" alt="tip" src="images/note.gif"> Arguably, you should <span style="font-weight: bold; text-decoration: underline;">always</span> strive for calling <span style="font-style: italic;">beginTask()</span>/<span style="font-style: italic;">done()</span>.
-The reasons for this are buried in the fact that you in principle never
-know when you are being called as a subtask. If you don't 'complete'
-the monitor, the parent can end up with an incorrect count for its own
-task. The full rationale is covered more below, in the section <a href="#Ensure_to_always_complete_your_monitor">"Ensure to always complete your monitor!"</a>.<br>
+Imagine you need to invoke another method that accepts an IProgressMonitor.
+What are the responsibilities of the caller and what are the responsibilities
+of the callee?
+<p>
+The caller:
+<ul>
+<li><b>Will</b> pass an IProgressMonitor instance which has not had <code>beginTask</code> invoked on it yet
+ (or an implementation such as SubMonitor which permits beginTask to be invoked multiple times).</li>
+<li><b>Will not</b> expect that the callee invokes <code>done()</code> on the monitor. The
+ caller must either use an SubMonitor (or a similar implementation which does not require <code>done()</code>
+ to be invoked), or it must take responsibility for calling <code>done()</code> on the monitor after the
+ callee has finished.</li>
+<li><b>Will not</b> pass in a null monitor unless the JavaDoc for the callee says that it accepts null.</li>
+<li><b>Will</b> pass in a monitor which ignores the String argument to <code>beginTask</code> unless the JavaDoc
+ for the callee says that it requires otherwise.</li>
+</ul>
+The callee:
+<ul>
+<li><b>Will</b> call <code>beginTask</code> 0 or 1 times on the monitor, at its option.</li>
+<li><b>Will not</b> promise to call <code>done()</code> on the monitor, although it is allowed to do so.</li>
+<li><b>Will not</b> call <code>setCanceled</code> on the monitor.</li>
+<li><b>Will not</b> accept a null monitor unless its JavaDoc says otherwise.</li>
+<li><b>Will not</b> expect the caller to do anything with the string passed to <code>beginTask</code> unless
+ its JavaDoc says otherwise.</li>
+</ul>
-<h3>Delegating use of a progress monitor to subtasks</h3>
+In practice, callers will be using SubMonitor wherever possible and method
+implementations will not be calling <code>done()</code>. This means that the only
+calls to <code>done()</code> will occur in root-level methods (methods which obtain
+their own IProgressMonitor via some mechanism other than having it passed it as a method parameter).
-Above for the IN_USE state I mentioned that it&rsquo;s very easy to get things wrong; <span style="font-style: italic;">beginTask()</span>
-should never be called more than once. This frequently happens in code
-that doesn&rsquo;t correctly understand the implications of the
-contract. Specifically, such code pass on the same instance it has been
-given to subtasks, and those subtasks; not aware that the caller
-already has begun following the contract, also tries following the
-contract in the expected manner &ndash; i.e. they start by doing a <span style="font-style: italic;">beginTask()</span>.<br>
+<h2>5.0 Different versions of Eclipse</h2>
-<br>
+In Eclipse 4.5 (Mars) and earlier, it was standard practice for method implementations
+to invoke <code>done()</code> on any monitor passed in as an argument and for the caller
+to rely upon this fact.
+<p>
+In Eclipse 4.6 (Neon), method implementations should still invoke <code>done()</code> if
+they did so previously. Callers are also required to either invoke <code>done()</code>
+or select a monitor implementation like SubMonitor which doesn't require the use of
+<code>done()</code>.
+<p>
+In Eclipse 4.7 (Oxygen) and higher, method implementations are not required to invoke
+<code>done()</code>. Callers must either invoke <code>done()</code> or select a monitor
+implementation like SubMonitor which doesn't require the use of <code>done()</code>.
-Thus, passing on a monitor instance is almost always wrong unless the
-code knows exactly what the implications are. So the rule becomes: In
-the general case, a piece of code that has received a progress monitor
-from a caller should always assume that the instance they are given is
-theirs and thus completely follow the <span style="font-style: italic;">beginTask()</span>/<span style="font-style: italic;">done()</span>
-protocol, and if it has subtasks that also needs a progress monitor,
-they should be given their own monitor instances through further use of
-the <span style="font-style: italic;">SubProgressMonitor</span> implementation that wraps the &lsquo;top-level&rsquo; monitor and correctly passes on <span style="font-style: italic;">worked()</span> calls etc (more on this below).<br>
+<h3>5.1 Changes in Eclipse 4.6</h3>
-<br>
+The following changes were made in Eclipse 4.6:
-Sample code to illustrate this:<br>
+<ul>
+<li>SubMonitor now has a static <code>done(IProgressMonitor)</code> method that can be used to
+ call <code>done()</code> on a possibly-null IProgressMonitor instance.</li>
+<li>The recommended policy for checking cancellation has changed. Rather than
+ using explicit cancellation checks, clients should rely on the implicit
+ cancellation checks done by SubMonitor.split.</li>
+<li>SubProgressMonitor is now deprecated.</li>
+</ul>
-<div style="margin-left: 40px;">
-<pre>monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>// figure some things out such as number of items to process etc&hellip;<br>try<br> {<br> monitor.beginTask(&hellip;)<br> // do stuff and call worked() for each item processed, and check for cancellation<br> &hellip;<br> // farm out a piece of the work that is logically done by &lsquo;me&rsquo; to something else<br> someThing.doWork(new SubProgressMonitor(monitor,&hellip;))<br> // farm out another piece of the work that is logically done by &lsquo;me&rsquo; to something else<br> anotherThing.doWork(new SubProgressMonitor(monitor,&hellip;))<br> }<br>finally<br> {<br> monitor.done()<br> }<br></pre>
+As of Eclipse 4.6 (Neon), any client code that obtains a root monitor (any monitor
+that isn't passed in as a method argument) is responsible for invoking <code>done()</code>
+on that monitor. It must not rely on the methods it calls to invoke
+<code>done()</code>. Please see the
+<a href="https://www.eclipse.org/eclipse/development/porting/eclipse_4_6_porting_guide.html">Migration guide</a>
+for more information on how to locate such code.
+<p>
+Method implementations that previously invoked <code>done()</code> should
+continue to do so, since the root monitors need to be updated first.
+
+<h3>5.2 Migrating from SubProgressMonitor to SubMonitor</h3>
+
+Eclipse 3.2 and earlier used SubProgressMonitor for nesting progress monitors. This class is
+deprecated as of Eclipse 4.6 (Neon). It has been replaced by SubMonitor.
+<p>
+The process for converting code which used SubProgressMonitor into SubMonitor is:
+<ul>
+<li>Calls to <code>IProgressMonitor.beginTask</code> on the root monitor should be replaced by a call
+ to <code>SubMonitor.convert</code>. Keep the returned SubMonitor around as a local variable and refer
+ to it instead of the root monitor for the remainder of the method.</li>
+<li>All calls to <code>new SubProgressMonitor(IProgressMonitor, int)</code> should be replaced by calls to
+ <code>SubMonitor.split(int)</code>.</li>
+<li>If a SubProgressMonitor is constructed using the SUPPRESS_SUBTASK_LABEL flag, replace it with the
+ two-argument version of <code>SubMonitor.split(int, int)</code> using <code>SubMonitor.SUPPRESS_SUBTASK</code>
+ as the second argument.</li>
+<li>It is not necessary to call done on an instance of <code>SubMonitor</code>.</li>
+<li>There is no drop-in replacement for PREPEND_MAIN_LABEL_TO_SUBTASK. PREPEND_MAIN_LABEL_TO_SUBTASK
+ made use of string arithmetic that didn't handle translation well. Clients that were using this
+ previously should switch to using fully-formatted task labels instead.
+</ul>
-</div>
+Note that <code>SubMonitor.convert(monitor, ticks)</code> is <b>not</b> a direct replacement for
+<code>new SubProgressMonitor(monitor, ticks)</code>. The former fully consumes a
+monitor which hasn't had ticks allocated on it yet and creates a new monitor with the given
+number of ticks allocated. The latter consumes only the given number of ticks from an input
+monitor which has already had ticks allocated and produces a monitor with no ticks allocated.
+If you attempt to do a search-and-replace of one to the other, your progress reporting won't work.
+
+<h3>5.3 Changes in Eclipse 4.7</h3>
+
+In Eclipse 4.7 (Oxygen) and higher, method implementations that receive a progress monitor are
+not required to invoke <code>done()</code> on it. Such calls may be removed if they were present
+in earlier versions.
+<p>
+Methods in plugins that are also intended for use with earlier Eclipse versions should continue calling
+<code>done()</code> as long as those earlier Eclipse versions are still being supported by the plugin.
+
+<h2>6.0 The protocol of <i>IProgressMonitor</i></h2>
+
+This section is for those of you doing something advanced. What if you want to implement your own
+IProgressMonitor or can't use the SubMonitor helper class? In that case you'll need
+to work with the IProgressMonitor contracts directly.
+<p>
+An IProgressMonitor instance can be in one of three states. Any given
+implementation may or may not track state changes and may or may
+not do anything about them.
+<p>
+
+<b>UNALLOCATED</b>
+<p>
+This is the initial state of a newly created <code>IProgressMonitor</code> instance,
+before <code>beginTask()</code> has been called to allocate ticks. Attempting to
+call <code>worked()</code> or otherwise consume ticks from a monitor in this state is an error.
+From here the monitor can enter the ALLOCATED state as a result of a <code>beginTask()</code>
+call or the FINISHED <code>done()</code> state as a result of a call to <code>done()</code>.
+<p>
+<b>ALLOCATED</b>
+<p>
+The monitor enters this state after the first and only call to <code>beginTask()</code>
+has allocated ticks for the monitor. Attempting to call <code>beginTask()</code> in this
+state is an error. From here the monitor can enter the FINISHED state as a result of a
+<code>done()</code> call.
+<p>
+<b>FINISHED</b>
+<p>
+The monitor enters this state after the first call to <code>done()</code>.
+Unlike <code>beginTask()</code>, <code>done()</code> may be called any number of times.
+However, only the first call to <code>done()</code> has any effect.
+Reporting work or calling <code>beginTask()</code> on a FINISHED monitor is a programming
+error and will have no effect. Unless the implementation says otherwise, <code>done()</code> must always
+be called on a monitor once <code>beginTask()</code> has been called.
+It is not necessary to call <code>done()</code> on a monitor in the UNALLOCATED
+state.
+</ul>
-Note that each <span style="font-style: italic;">doWork()</span> call gets a new instance of a <span style="font-style: italic;">SubProgressMonitor</span>; such instances can and should not be reused for all the protocol reasons already discussed.<br>
-
-<br>
-
-The only time a single instance of a monitor passed to, or retrieved
-by, a certain piece code can be reused in multiple places (e.g.
-typically methods called by the original receiver), is when the code in
-such methods is so intimately coupled so that they in effect
-constitute a single <span style="font-style: italic;">try</span>/<span style="font-style: italic;">finally</span> block. Also, for this to work each method must know exactly who does <span style="font-style: italic;">beginTask()</span>/<span style="font-style: italic;">done()</span> calls, and also (don&rsquo;t forget this) how many work items they represent of the total reported to <span style="font-style: italic;">beginTask()</span>
-so that they can make the correct reports. Personally, I believe this
-is generally more trouble than it&rsquo;s worth &ndash; always follow
-the regular pattern of one receiver, one unique monitor instead and the
-code as a whole is more maintainable.<br>
-
-<h3>Managing the item count</h3>
-
-This section is about how to do the initial <span style="font-style: italic;">beginTask()</span> call and report the amount of total work expected, and then ideally report <span style="text-decoration: underline;">exactly</span>
-that many items to the monitor. It is ok to end up not reporting all
-items in one particular case: when the job is aborted (due to
-cancellation by user, an exception thrown and so on) &ndash; this is
-normal and expected behavior and we will wind up in the <span style="font-style: italic;">finally</span> clause where <span style="font-style: italic;">done()</span> is called.<br>
-
-<br>
-
-It is however sloppy technique to &lsquo;just pick a number&rsquo; for the total and then call <span style="font-style: italic;">worked()</span>,
-reporting a number and hope that the total is never exceeded. Either
-way this can cause very erratic behavior of the absolute top level and
-user visible progress bar (it is for a human we&rsquo;re doing this
-after all) &ndash; if the total is too big compared to the actual items
-reported, a progress bar will move slowly, perhaps not at all due to
-scaling and then suddenly (at the <span style="font-style: italic;">done()</span>
-call) jump directly to completed. If the total is too small, the bar
-will quickly reach &rsquo;100%&rsquo; or very close to it and then stay
-there &lsquo;forever&rsquo;. <br>
-
-<br>
-
-So, first and foremost: do <span style="text-decoration: underline;">not</span>
-guess on the number of work items. It&rsquo;s a simple binary answer:
-either you know exactly how many things that will be
-processed&hellip;or you don&rsquo;t know. It IS ok to not know! If you
-don't know, just report&nbsp;<span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> as the total number, call <span style="font-style: italic;">worked()</span>
-to your hearts content and a clever progress monitor implementation
-will still do something useful with it. Note that each (sub)task can
-and should make its own decision on what it knows or not. If all are
-following the protocol it will ensure proper behavior at the outer,
-human visible end. A heads up though: never call the <span style="font-style: italic;">SubProgressMonitor(parentMonitor, subticks)</span> constructor using&nbsp;<span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> for subticks - this is wrong! More on this later.<br>
-
-<h3>How to call <span style="font-style: italic;">beginTask()</span> and <span style="font-style: italic;">worked()</span></h3>
-
-There are typically two basic patterns where you know how many items
-you want to process: either you are going to call several different
-methods to achieve the full result, or you are going to call one method
-for each instance in a collection of some sort. Either way you know the
-total item count to process (the number of methods or the size of the
-collection). Variations of this are obviously combinations of these
-basic patterns&nbsp;so just multiply and sum it all up.<br>
-
-<br>
-
-There is sometimes a benefit of scaling your total a bit. So, instead of reporting &lsquo;3&rsquo; as the total (and do <span style="font-style: italic;">worked(1)</span> for each item) you may consider scaling with, say 1000, and reporting &lsquo;3000&rsquo; instead (and do <span style="font-style: italic;">worked(1000)</span>
-for each item). The benefit comes up when you are farming out work to
-subtasks through a SubProgressMonitor; since they may internally have a
-very different total, especially one that is much bigger than your
-total, you give them (and the monitor instance) some &lsquo;room&rsquo;
-to more smoothly consume and display the allotment you&rsquo;ve given
-them (more explanations below on how to mix <span style="font-style: italic;">worked()</span> and <span style="font-style: italic;">SubProgressMonitor</span>
-work below). Consider that you say &lsquo;my total is 3&rsquo; and you
-then give a subtask &lsquo;1&rsquo; of these to consume. If the subtask
-now will report several thousand <span style="font-style: italic;">worked()</span>
-calls, and assuming that the actual human visible progress bar also has
-the room, the internal protocol between a SubProgressMonitor and
-it&rsquo;s wrapped monitor will scale better and give more smooth
-movement if you instead would have given it &lsquo;1000&rsquo; out of
-&lsquo;3000&rsquo;. Or not - the point is really that you don't know
-what monitor implementation will be active, all you can do is give some
-information. How it's then displayed in reality is a matter of how
-nifty the progress monitor implementation is.<br>
-
-<br>
-
-A sample of simple calls:<br>
-
-<pre style="margin-left: 40px;">monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>int total = 3 // hardcoded and known<br>try<br> {<br> monitor.beginTask(total)<br> <br> // item 1<br> this.doPart1()<br> monitor.worked(1)<br><br> // item 2<br> this.doPart2()<br> monitor.worked(1)<br><br> // item 3<br> this.doPart3()<br> monitor.worked(1)<br> }<br>finally<br> {<br> monitor.done()<br> }</pre>
-
-No reason to scale and no collection to dynamically compute.<br>
-
-<br>
-
-A more elaborate sample:<br>
-
-<pre style="margin-left: 40px;">monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>int total = thingyList.size() * 3 + 2<br>try<br> {<br> monitor.beginTask(total)<br> <br> // item 1<br> this.doBeforeAllThingies()<br> monitor.worked(1)<br> <br> // items 2 to total-1<br> for (Thingy t : thingyList)<br> {<br> t.doThisFirst()<br> monitor.worked(1)<br> t.thenDoThat()<br> monitor.worked(1)<br> t.lastlyDoThis()<br> monitor.worked(1)<br> }<br><br> // final item <br> this.doAfterAllThingies()<br> monitor.worked(1)<br> }<br>finally<br> {<br> monitor.done()<br> }<br></pre>
-
-<h3>Mixing straightforward calls with subtasks</h3>
-
-I was initially confused by how to report progress when I farmed out
-work to subtasks. I experienced &lsquo;reporting too much work&rsquo;
-since I didn&rsquo;t understand when to call and when to not call <span style="font-style: italic;">worked()</span>. Once I caught on, the rule is very simple however: calling a subtask with a <span style="font-style: italic;">SubProgressMonitor</span> is basically an implicit call to <span style="font-style: italic;">worked()</span> with the amount allotted to the subtask. So instead of this:<br>
-
-<pre style="margin-left: 40px;">monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>int scale = 1000<br>int total = 3 // hardcoded and known<br>try<br> {<br> monitor.beginTask(total * scale)<br> <br> // item 1<br> this.doPart1()<br> monitor.worked(1 * scale)<br><br> // item 2<br> this.doPart2(new SubProgressMonitor(monitor, 1 * scale)) // allot 1 item<br> monitor.worked(1 * scale) // WRONG! Not needed, already managed by the SubProgressMonitor<br><br> // item 3<br> this.doPart3()<br> monitor.worked(1 * scale)<br> }<br>finally<br> {<br> monitor.done()<br> }</pre>
-
-You should just leave out the second call to <span style="font-style: italic;">worked()</span>.<br>
-
-<h4><img style="width: 62px; height: 13px;" alt="Tip" src="images/note.gif"> Never pass <span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> (or any other <span style="text-decoration: underline;">negative</span> value) when creating a <span style="font-style: italic;">SubProgressMonitor()</span> wrapper!</h4>
-
-A
-situation I just the other day experienced was when doing an <span style="font-style: italic;">IProgressMonitor.UNKNOWN</span>
-number of&nbsp;things - I needed to call a subtask, and hence I set up to
-call it using a <span style="font-style: italic;">SubProgressMonitor(parent, subticks)</span> but
-I realized that I hadn't ever considered how the sub monitor should be
-created - how many subticks it should be given - in the unknown case. I
-figured it should be ok to pass&nbsp;<span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> there also. However, when
-later trying my code I saw to my horror that my progress bar went
-backwards! Not the effect I figured on...<br>
-
-<br>
-
-As it turns out, this is because the implementation (as of Eclipse
-3.2M3) blindly uses the incoming ticks as a scaling factor. However, it
-goes haywire when it receives a negative value (and <span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> happens to have a value of -1). It does computations with it, and it ends up calling <span style="font-style: italic;">worked()</span>
-with negative values which my monitor tried to process...that code is
-now fixed to be more resilient in such cases. I've filed <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=119018">bug #119018</a> to
-request that <span style="font-style: italic;">SubProgressMonitor</span> handles it better and/or document that negative values is a bad idea for the constructor call.<br>
-
-<br>
-
-Whatever, passing&nbsp;<span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> is incorrect in any case. If you have called <span style="font-style: italic;">beginTask()</span> using&nbsp;<span style="font-style: italic;">IProgressMonitor.UNKNOWN</span> you can gladly pass in any reasonable tick value to a <span style="font-style: italic;">SubProgressMonitor</span>, it will give the correct result.<br>
-<h3><a name="Ensure_to_always_complete_your_monitor"></a>Ensure to always complete your monitor!</h3>
-Consider the concept described in the previous section: the important
-thing here is that basically, you say that you have three distinct and
-logical things to do, and then you tick them off - but one of the ticks
-is actually farmed out to a subtask through a <span style="font-style: italic;">SubProgressMonitor</span>. You don't really know how many distinct and logical things the subtask has to do, nor should you care. The mechanics of using a <span style="font-style: italic;">SubProgressMonitor</span> makes the advancement of one of&nbsp;<span style="font-weight: bold;">your</span>
-ticks happen in the correct way. So, the end&nbsp;expectation is that
-once you reach the end of your three things, the monitor you have, have
-actually fulfilled the count you intended - the internal state of it
-should reflect this: &quot;the user said three things should happen and my
-work count is now indeed '3'&quot;.<br>
-<br>
-But, as I recently found out, this can fail. Specifically, I blindly invoked <span style="font-style: italic;">IProject.build()</span> on a project which had no builders configured. To this method I sent in a <span style="font-style: italic;">SubProgressMonitor</span>
-and allotted it one 'tick' of mine. But, as it turned out, internally
-it never used the monitor it got, presumably because there was no work
-to perform - not very unreasonable in a sense. However, this did have
-the effect that one of my ticks never got, well, 'tocked' :-). I could
-solve this specific problem by simply checking if there was any
-builders configured, and if there were none, I simply advanced the tick
-by&nbsp;<span style="font-style: italic;">worked(1)</span> instead. But, it requires me, the caller, to make assumptions on the internal workings of the subtask, which is never good.<br>
-<br>
-This is not a huge problem of course. But, I think it would make sense to always act the same. The code resulting from <span style="font-style: italic;">IProject.build()</span> could just call <span style="font-style: italic;">beginTask(&quot;&quot;, countOfBuilders)</span> regardless of if countOfBuilders was 0, iterate over the empty array or whatever, and then call <span style="font-style: italic;">done()</span>. This would correctly advance <span style="font-weight: bold;">my</span> tick.
-<h3>Cancellation</h3>
-
-The sample code above does not show cancellation checks. However, it
-is obviously recommended that users of a progress monitor actively
-check for cancellation to timely break out of the operation. The more
-(potentially) long-running, the more important of course. And remember:
-you don't know if the operation is running in a context that allows it
-to be canceled or not - so you just have to code defensively. A sample
-of how it should look could be this:<br>
-
-<pre style="margin-left: 40px;">monitor = &hellip; // somehow get a new progress monitor which is in a pristine state<br>try<br> {<br> monitor.beginTask(thingyList.size())<br> <br> for (Thingy t : thingyList)<br> {<br> if(monitor.isCanceled())<br> throw new OperationCanceledException();<br> t.doSomething()<br> monitor.worked(1) <br> }<br> }<br>finally<br> {<br> monitor.done()<br>}<br></pre>
-
-<h3>The <span style="font-style: italic;">NullProgressMonitor</span></h3>
-
-A common pattern is to allow callers to skip sending a monitor, i.e. sending &lsquo;<span style="font-style: italic;">null</span>&rsquo;. A simple and convenient way to deal with such calls is this:<br>
-
-<pre style="margin-left: 40px;">public void doIt(IProgressMonitor monitor)<br>{<br> // ensure there is a monitor of some sort<br> if(monitor == null)<br> monitor = new NullProgressMonitor();<br><br> try<br> {<br> monitor.beginTask(thingyList.size())<br> <br> for (Thingy t : thingyList)<br> {<br> if(monitor.isCanceled())<br> throw new OperationCanceledException();<br> t.doSomething()<br> monitor.worked(1) <br> }<br> }<br>finally<br> {<br> monitor.done()<br> } <br>}<br></pre>
-
-<h2>Conclusion</h2>
-
-I believe that by diligently following these rules and patterns, you
-will never have a problem in using the progress monitor mechanism.
-Obviously, it requires implementations to follow the contract as well.
-But remember, if you mistreat the protocol you will sooner or later end
-up talking to a progress monitor implementation that is stern and will
-simply throw an exception or give strange visual effects if you call
-it&rsquo;s <span style="font-style: italic;">beginTask()</span> one time too many. It&rsquo;s essentially valid if the <span style="font-style: italic;">IProgressMonitor</span> interface description is to be believed &ndash; and you will get blamed by your customer&hellip;
+<h3>6.1 Cancellation</h3>
+
+A monitor can become cancelled at any time due to activity on another thread.
+The monitor indicates that it has been cancelled by returning
+true from <code>isCanceled()</code>. When a long-running operation detects that
+it has been cancelled, it should abort its operation cleanly.
+<p>
+It is technically possible to cancel a monitor by invoking
+<code>setCanceled()</code> but you should
+never do this. A long-running method that wishes to cancel itself it should
+throw OperationCanceledException rather than invoking any particular method
+on its monitor.
+
+<h3>6.2 Threading</h3>
+
+All implementations of IProgressMonitor are single-threaded by default. Unless the
+JavaDoc for the specific monitor implementation says otherwise, all methods
+must be invoked on the same thread that instantiated the monitor. If the concrete
+type of the IProgressMonitor is unknown, it must be assumed to be single-threaded.
+
+<h3>6.3 Allocating ticks</h3>
+
+When using <code>beginTask</code> to allocate ticks on an IProgressMonitor, the caller should
+always allocate at least 1000 ticks. Many root monitors use this value to set
+the resolution for all subsequent progress reporting, even if the ticks are
+later subdivided using a SubMonitor.
+<p>
+SubMonitor users don't need to worry about this since <code>SubMonitor.convert</code>
+does this internally when converting an unknown monitor.
+<p>
+
+<h3>6.4 Passing strings to beginTask</h3>
+
+At the lowest level, any method that needs to allocate ticks ends up calling
+<code>beginTask</code>. Usually this is done indirectly by a call to
+<code>SubMonitor.convert(...)</code>. Unfortunately, <code>beginTask</code>
+also takes a string argument which root monitors use to set the task name.
+<p>
+Every long-running operation needs to allocate ticks but most don't want to
+modify the task name. For this reason, most callers of <code>beginTask</code>
+call it with the empty string or a temporary string that isn't intended
+to be seen by the end user. Similarly, most implementations of
+<code>beginTask</code> are expected to ignore the string argument.
+<p>
+The exception is root monitors. Many root monitors display the string argument
+somewhere. For this reason, any code that obtains a root monitor is expected
+to convert it to a form that will filter out the string argument
+before passing it to another method.
+<p>
+The default expectation is that progress monitors passed as parameters will
+do this filtering. Any method that receives a progress monitor and does not
+want the <code>beginTask(...)</code> argument filtered must say so clearly in
+its JavaDoc.
+
+<h3>6.5 IProgressMonitor.UNKNOWN</h3>
+
+IProgressMonitor.UNKNOWN is only supported by root monitors and should never
+be used by method implementations which receive a progress monitor as a parameter.
+
+<h3>6.6 Task names and performance concerns</h3>
+
+As of the time of this writing (Eclipse 4.6), several of the root monitors
+in Eclipse have expensive implementations of <code>setTaskName(...)</code>
+and <code>subTask(...)</code>. Plugin authors are advised not to call
+these methods more than 3 times per second. Doing so may introduce
+performance problems. See
+<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=445802">Eclipse bug 445802</a>
+for more information.
+<p>
</body>
</html>

Back to the top