Skip to main content
summaryrefslogtreecommitdiffstats
blob: 53231d4f7a3b6f2c3d30029bb51cf48642c8d1a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>  
  <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
  <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; 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">Using Progress Monitors</h1>
<blockquote>
  <b>Summary</b>

  <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>

  <p><b> By Stefan Xenos, Google</b> <br>
October 19, 2016<font size="-1"></font> </p>

</blockquote>

<hr width="100%">

<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>

<p>
In some rare cases, you really need to perform an explicit cancellation check
at a specific time and can't rely on the intermittent cancellation checks done
by <code>split</code>. In such cases, you can use the <code>SubMonitor.checkCanceled</code>
utility introduced in Eclipse 4.7.
<p>
For example, this code converts an IProgressMonitor to a SubMonitor while performing
a guaranteed cancellation check:
<pre>
    SubMonitor subMonitor = SubMonitor.convert(monitor).checkCanceled();
</pre>

<h3>2.5 Testing and Debugging</h3>

Whenever you add or change progress monitoring in a method, you should test it by
enabling the progress monitor self-tests while you run your code. To do this, add
the following tracing options to an Eclipse .options file:
<p>
<pre>
org.eclipse.equinox.common/debug=true
org.eclipse.equinox.common/progress_monitors=true
</pre>
<p>
Once enabled, you will see a warning written to the log whenever your code violates
the API contracts on a SubMonitor. The tracing options can also be enabled in the
<i>tracing</i> tab of any launch configuration. If you maintain any code that reports
progress, it's generally a good idea to leave these options enabled at all times.
<p>
If you see nothing it either means that your code is working perfectly or that the
diagnostic tool isn't running. You can confirm that the diagnostic tool is running by
using your debugger to confirm that the following variable is true:

<pre>
org.eclipse.core.internal.runtime.TracingOptions.debugProgressMonitors
</pre>
<p>
More information about enabling Eclipse tracing options can be found 
<a href="https://wiki.eclipse.org/FAQ_How_do_I_use_the_platform_debug_tracing_facility">here</a>.

<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);

         // Use 30% of the progress to do some work
         someChildTask(subMonitor.split(30));

         // Use the remaining 70% of the progress to do some more work
         someChildTask(subMonitor.split(70));
     }
</pre>

<h3>3.2 Branches</h3>

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.

<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>

</ul>

<h2>4.0 Responsibilities of callers and callees</h2>

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>

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).

<h2>5.0 Different versions of Eclipse</h2>

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>.
 

<h3>5.1 Changes in Eclipse 4.6</h3>

The following changes were made in Eclipse 4.6:

<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>

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>

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.
<p>
Eclipse 4.7 also introduced the <code>SubMonitor.checkCanceled</code> utility for convenient
explicit cancellation checks.

<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>

<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