org.eclipse.core.runtime
Class SubMonitor
java.lang.Object
org.eclipse.core.runtime.SubMonitor
-
All Implemented Interfaces:
-
IProgressMonitor,
IProgressMonitorWithBlocking
-
public final class SubMonitor
- extends
Object
- implements
IProgressMonitorWithBlocking
A progress monitor that uses a given amount of work ticks from a parent monitor. This is intended as a
safer, easier-to-use alternative to SubProgressMonitor. The main benefits of SubMonitor over
SubProgressMonitor are:
- It is not necessary to call beginTask() or done() on an instance of SubMonitor.
- SubMonitor has a simpler syntax for creating nested monitors.
- SubMonitor is more efficient for deep recursion chains.
- SubMonitor has a setWorkRemining method that allows the remaining space on the monitor to be
redistributed without reporting any work.
- SubMonitor protects the caller from common progress reporting bugs in a called method. For example,
if a called method fails to call done() on the given monitor or fails to consume all the ticks on
the given monitor, the parent will correct the problem after the method returns.
USAGE:
When implementing a method that accepts an IProgressMonitor:
- At the start of your method, use
SubMonitor.convert(...).
to convert the IProgressMonitor
into a SubMonitor.
- Use
SubMonitor.newChild(...)
whenever you need to call another method that
accepts an IProgressMonitor.
DEFAULT BEHAVIOR:
When writing JavaDoc for a method that accepts an IProgressMonitor, you should assume the
following default behavior unless the method's JavaDoc says otherwise:
- It WILL call beginTask on the IProgressMonitor.
- It WILL NOT accept a null argument.
- It WILL call done on the IProgressMonitor.
BEST PRACTISES:
We recommend that newly-written methods follow the given contract:
- It WILL call beginTask on the IProgressMonitor.
- It WILL accept a null argument, indicating that no progress should be reported and the operation cannot be cancelled.
- It WILL NOT call done on the IProgressMonitor, leaving this responsibility up to the caller.
If you wish to follow these conventions, you may copy and paste the following text into your method's JavaDoc:
@param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
to call done() on the given monitor. Accepts null
, indicating that no progress should be
reported and that the operation cannot be cancelled.
Example: Recommended usage
This example demonstrates how the recommended usage of SubMonitor
makes it unnecessary to call
IProgressMonitor.done() in most situations.
It is never necessary to call done() on a monitor obtained from convert
or progress.newChild()
.
In this example, there is no guarantee that monitor
is an instance of SubMonitor
, making it
necessary to call monitor.done()
. The JavaDoc contract makes this the responsibility of the caller.
// param monitor the progress monitor to use for reporting progress to the user. It is the caller's responsibility
// to call done() on the given monitor. Accepts null
, indicating that no progress should be
// reported and that the operation cannot be cancelled.
//
void doSomething(IProgressMonitor monitor) {
// Convert the given monitor into a progress instance
SubMonitor progress = SubMonitor.convert(monitor, 100);
// Use 30% of the progress to do some work
doSomeWork(progress.newChild(30));
// Advance the monitor by another 30%
progress.worked(30);
// Use the remaining 40% of the progress to do some more work
doSomeWork(progress.newChild(40));
}
Example: Default usage
You will often need to implement a method that does not explicitly stipulate that calling done() is the responsibility
of the caller. In this case, you should use the following pattern:
// param monitor the progress monitor to use for reporting progress to the user, or null
indicating
// that no progress should be reported and the operation cannot be cancelled.
//
void doSomething(IProgressMonitor monitor) {
// Convert the given monitor into a progress instance
SubMonitor progress = SubMonitor.convert(monitor, 100);
try {
// Use 30% of the progress to do some work
doSomeWork(progress.newChild(30));
// Advance the monitor by another 30%
progress.worked(30);
// Use the remaining 40% of the progress to do some more work
doSomeWork(progress.newChild(40));
} finally {
if (monitor != null) {
monitor.done();
}
}
}
Example: Branches
This example demonstrates how to smoothly report progress in situations where some of the work is optional.
void doSomething(IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, 100);
if (condition) {
// Use 50% of the progress to do some work
doSomeWork(progress.newChild(50));
}
// Don't report any work, but ensure that we have 50 ticks remaining on the progress monitor.
// If we already consumed 50 ticks in the above branch, this is a no-op. Otherwise, the remaining
// space in the monitor is redistributed into 50 ticks.
progress.setWorkRemaining(50);
// Use the remainder of the progress monitor to do the rest of the work
doSomeWork(progress.newChild(50));
}
Please beware of the following anti-pattern:
if (condition) {
// Use 50% of the progress to do some work
doSomeWork(progress.newChild(50));
} else {
// Bad: Causes the progress monitor to appear to start at 50%, wasting half of the
// space in the monitor.
progress.worked(50);
}
Example: Loops
This example demonstrates how to report progress in a loop.
void doSomething(IProgressMonitor monitor, Collection someCollection) {
SubMonitor progress = SubMonitor.convert(monitor, 100);
// Create a new progress monitor that uses 70% of the total progress and will allocate one tick
// for each element of the given collection.
SubMonitor loopProgress = progress.newChild(70).setWorkRemaining(someCollection.size());
for (Iterator iter = someCollection.iterator(); iter.hasNext();) {
Object next = iter.next();
doWorkOnElement(next, loopProgress.newChild(1));
}
// Use the remaining 30% of the progress monitor to do some work outside the loop
doSomeWork(progress.newChild(30));
}
Example: Infinite progress
This example demonstrates how to report logarithmic progress in situations where the number of ticks
cannot be easily computed in advance.
void doSomething(IProgressMonitor monitor, LinkedListNode node) {
SubMonitor progress = SubMonitor.convert(monitor);
while (node != null) {
// Regardless of the amount of progress reported so far,
// use 0.01% of the space remaining in the monitor to process the next node.
progress.setWorkRemaining(10000);
doWorkOnElement(node, progress.newChild(1));
node = node.next;
}
}
This class can be used without OSGi running.
-
Since:
- org.eclipse.equinox.common 3.3
Method Summary
|
void
|
beginTask
(
String name,
int totalWork)
Starts a new main task. |
void
|
clearBlocked
()
Clears the blocked state of the running operation. |
static
SubMonitor
|
convert
(
IProgressMonitor monitor)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. |
static
SubMonitor
|
convert
(
IProgressMonitor monitor,
int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks. |
static
SubMonitor
|
convert
(
IProgressMonitor monitor,
String taskName,
int work)
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks. |
void
|
done
()
Notifies that the work is done; that is, either the main task is completed
or the user canceled it. |
protected static boolean
|
eq
(
Object o1,
Object o2)
|
void
|
internalWorked
(double work)
Internal method to handle scaling correctly. |
boolean
|
isCanceled
()
Returns whether cancelation of current operation has been requested. |
SubMonitor
|
newChild
(int totalWork)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. |
SubMonitor
|
newChild
(int totalWork,
int suppressFlags)
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. |
void
|
setBlocked
(
IStatus reason)
Indicates that this operation is blocked by some background activity. |
void
|
setCanceled
(boolean b)
Sets the cancel state to the given value. |
void
|
setTaskName
(
String name)
Sets the task name to the given value. |
SubMonitor
|
setWorkRemaining
(int workRemaining)
Sets the work remaining for this SubMonitor instance. |
void
|
subTask
(
String name)
Notifies that a subtask of the main task is beginning. |
void
|
worked
(int work)
Notifies that a given number of work unit of the main task
has been completed. |
Methods inherited from class java.lang.
Object
|
clone,
equals,
finalize,
getClass,
hashCode,
notify,
notifyAll,
toString,
wait,
wait,
wait
|
SUPPRESS_SUBTASK
public static final int SUPPRESS_SUBTASK
- May be passed as a flag to newChild. Indicates that the calls
to subTask on the child should be ignored. Without this flag,
calling subTask on the child will result in a call to subTask
on its parent.
-
See Also:
-
Constant Field Values
SUPPRESS_BEGINTASK
public static final int SUPPRESS_BEGINTASK
- May be passed as a flag to newChild. Indicates that strings
passed into beginTask should be ignored. If this flag is
specified, then the progress monitor instance will accept null
as the first argument to beginTask. Without this flag, any
string passed to beginTask will result in a call to
setTaskName on the parent.
-
See Also:
-
Constant Field Values
SUPPRESS_SETTASKNAME
public static final int SUPPRESS_SETTASKNAME
- May be passed as a flag to newChild. Indicates that strings
passed into setTaskName should be ignored. If this string
is omitted, then a call to setTaskName on the child will
result in a call to setTaskName on the parent.
-
See Also:
-
Constant Field Values
SUPPRESS_ALL_LABELS
public static final int SUPPRESS_ALL_LABELS
- May be passed as a flag to newChild. Indicates that strings
passed to setTaskName, subTask, and beginTask should all be ignored.
-
See Also:
-
Constant Field Values
SUPPRESS_NONE
public static final int SUPPRESS_NONE
- May be passed as a flag to newChild. Indicates that strings
passed to setTaskName, subTask, and beginTask should all be propagated
to the parent.
-
See Also:
-
Constant Field Values
convert
public static
SubMonitor convert(
IProgressMonitor monitor)
-
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor. It is
not necessary to call done() on the result, but the caller is responsible for calling
done() on the argument. Calls beginTask on the argument.
This method should generally be called at the beginning of a method that accepts
an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
-
-
-
Parameters:
-
monitor
- monitor to convert to a SubMonitor instance or null. Treats null
as a new instance of NullProgressMonitor
.
-
Returns:
- a SubMonitor instance that adapts the argument
convert
public static
SubMonitor convert(
IProgressMonitor monitor,
int work)
-
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks. It is not necessary to call done() on the result,
but the caller is responsible for calling done() on the argument. Calls beginTask
on the argument.
This method should generally be called at the beginning of a method that accepts
an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
-
-
-
Parameters:
-
monitor
- monitor to convert to a SubMonitor instance or null. Treats null
as a new instance of NullProgressMonitor
. -
work
- number of ticks that will be available in the resulting monitor
-
Returns:
- a SubMonitor instance that adapts the argument
convert
public static
SubMonitor convert(
IProgressMonitor monitor,
String taskName,
int work)
-
Converts an unknown (possibly null) IProgressMonitor into a SubMonitor allocated
with the given number of ticks. It is not necessary to call done() on the result,
but the caller is responsible for calling done() on the argument. Calls beginTask
on the argument.
This method should generally be called at the beginning of a method that accepts
an IProgressMonitor in order to convert the IProgressMonitor into a SubMonitor.
-
-
-
Parameters:
-
monitor
- to convert into a SubMonitor instance or null. If given a null argument,
the resulting SubMonitor will not report its progress anywhere. -
taskName
- user readable name to pass to monitor.beginTask. Never null. -
work
- initial number of ticks to allocate for children of the SubMonitor
-
Returns:
- a new SubMonitor instance that is a child of the given monitor
setWorkRemaining
public
SubMonitor setWorkRemaining(int workRemaining)
-
Sets the work remaining for this SubMonitor instance. This is the total number
of ticks that may be reported by all subsequent calls to worked(int), newChild(int), etc.
This may be called many times for the same SubMonitor instance. When this method
is called, the remaining space on the progress monitor is redistributed into the given
number of ticks.
It doesn't matter how much progress has already been reported with this SubMonitor
instance. If you call setWorkRemaining(100), you will be able to report 100 more ticks of
work before the progress meter reaches 100%.
-
-
-
Parameters:
-
workRemaining
- total number of remaining ticks
-
Returns:
- the receiver
isCanceled
public boolean isCanceled()
-
Description copied from interface:
IProgressMonitor
- Returns whether cancelation of current operation has been requested.
Long-running operations should poll to see if cancelation
has been requested.
-
-
Specified by:
-
isCanceled
in interface
IProgressMonitor
-
-
Returns:
-
true
if cancellation has been requested,
and false
otherwise -
See Also:
-
IProgressMonitor.setCanceled(boolean)
setTaskName
public void setTaskName(
String name)
-
Description copied from interface:
IProgressMonitor
- Sets the task name to the given value. This method is used to
restore the task label after a nested operation was executed.
Normally there is no need for clients to call this method.
-
-
Specified by:
-
setTaskName
in interface
IProgressMonitor
-
-
Parameters:
-
name
- the name (or description) of the main task -
See Also:
-
IProgressMonitor.beginTask(java.lang.String, int)
beginTask
public void beginTask(
String name,
int totalWork)
- Starts a new main task. The string argument is ignored
if and only if the SUPPRESS_BEGINTASK flag has been set on this SubMonitor
instance.
This method is equivalent calling setWorkRemaining(...) on the receiver. Unless
the SUPPRESS_BEGINTASK flag is set, this will also be equivalent to calling
setTaskName(...) on the parent.
-
-
Specified by:
-
beginTask
in interface
IProgressMonitor
-
-
Parameters:
-
name
- new main task name -
totalWork
- number of ticks to allocate -
See Also:
-
IProgressMonitor.beginTask(java.lang.String, int)
done
public void done()
-
Description copied from interface:
IProgressMonitor
- Notifies that the work is done; that is, either the main task is completed
or the user canceled it. This method may be called more than once
(implementations should be prepared to handle this case).
-
-
Specified by:
-
done
in interface
IProgressMonitor
-
internalWorked
public void internalWorked(double work)
-
Description copied from interface:
IProgressMonitor
- Internal method to handle scaling correctly. This method
must not be called by a client. Clients should
always use the method worked(int).
-
-
Specified by:
-
internalWorked
in interface
IProgressMonitor
-
-
Parameters:
-
work
- the amount of work done
subTask
public void subTask(
String name)
-
Description copied from interface:
IProgressMonitor
- Notifies that a subtask of the main task is beginning.
Subtasks are optional; the main task might not have subtasks.
-
-
Specified by:
-
subTask
in interface
IProgressMonitor
-
-
Parameters:
-
name
- the name (or description) of the subtask
worked
public void worked(int work)
-
Description copied from interface:
IProgressMonitor
- Notifies that a given number of work unit of the main task
has been completed. Note that this amount represents an
installment, as opposed to a cumulative amount of work done
to date.
-
-
Specified by:
-
worked
in interface
IProgressMonitor
-
-
Parameters:
-
work
- a non-negative number of work units just completed
setCanceled
public void setCanceled(boolean b)
-
Description copied from interface:
IProgressMonitor
- Sets the cancel state to the given value.
-
-
Specified by:
-
setCanceled
in interface
IProgressMonitor
-
-
Parameters:
-
b
- true
indicates that cancelation has
been requested (but not necessarily acknowledged);
false
clears this flag -
See Also:
-
IProgressMonitor.isCanceled()
newChild
public
SubMonitor newChild(int totalWork)
-
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. It is not necessary to call beginTask
or done
on the
result. However, the resulting progress monitor will not report any work after the first
call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
or setWorkRemaining.
Each SubMonitor only has one active child at a time. Each time newChild() is called, the
result becomes the new active child and any unused progress from the previously-active child is
consumed.
This is property makes it unnecessary to call done() on a SubMonitor instance, since child
monitors are automatically cleaned up the next time the parent is touched.
////////////////////////////////////////////////////////////////////////////
// Example 1: Typical usage of newChild
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
doSomething(progress.newChild(50));
doSomethingElse(progress.newChild(50));
}
////////////////////////////////////////////////////////////////////////////
// Example 2: Demonstrates the function of active children. Creating children
// is sufficient to smoothly report progress, even if worked(...) and done()
// are never called.
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
for (int i = 0; i < 100; i++) {
// Creating the next child monitor will clean up the previous one,
// causing progress to be reported smoothly even if we don't do anything
// with the monitors we create
progress.newChild(1);
}
}
////////////////////////////////////////////////////////////////////////////
// Example 3: Demonstrates a common anti-pattern
void wrongMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// WRONG WAY: Won't have the intended effect, as only one of these progress
// monitors may be active at a time and the other will report no progress.
callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
}
void rightMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
Object someValue = computeValue(progress.newChild(50));
callMethod(progress.newChild(50), someValue);
}
-
-
-
Parameters:
-
totalWork
- number of ticks to consume from the receiver
-
Returns:
- new sub progress monitor that may be used in place of a new SubMonitor
newChild
public
SubMonitor newChild(int totalWork,
int suppressFlags)
-
Creates a sub progress monitor that will consume the given number of ticks from the
receiver. It is not necessary to call beginTask
or done
on the
result. However, the resulting progress monitor will not report any work after the first
call to done() or before ticks are allocated. Ticks may be allocated by calling beginTask
or setWorkRemaining.
Each SubMonitor only has one active child at a time. Each time newChild() is called, the
result becomes the new active child and any unused progress from the previously-active child is
consumed.
This is property makes it unnecessary to call done() on a SubMonitor instance, since child
monitors are automatically cleaned up the next time the parent is touched.
////////////////////////////////////////////////////////////////////////////
// Example 1: Typical usage of newChild
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
doSomething(progress.newChild(50));
doSomethingElse(progress.newChild(50));
}
////////////////////////////////////////////////////////////////////////////
// Example 2: Demonstrates the function of active children. Creating children
// is sufficient to smoothly report progress, even if worked(...) and done()
// are never called.
void myMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
for (int i = 0; i < 100; i++) {
// Creating the next child monitor will clean up the previous one,
// causing progress to be reported smoothly even if we don't do anything
// with the monitors we create
progress.newChild(1);
}
}
////////////////////////////////////////////////////////////////////////////
// Example 3: Demonstrates a common anti-pattern
void wrongMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// WRONG WAY: Won't have the intended effect, as only one of these progress
// monitors may be active at a time and the other will report no progress.
callMethod(progress.newChild(50), computeValue(progress.newChild(50)));
}
void rightMethod(IProgressMonitor parent) {
SubMonitor progress = SubMonitor.convert(parent, 100);
// RIGHT WAY: Break up method calls so that only one SubMonitor is in use at a time.
Object someValue = computeValue(progress.newChild(50));
callMethod(progress.newChild(50), someValue);
}
-
-
-
Parameters:
-
totalWork
- number of ticks to consume from the receiver
-
Returns:
- new sub progress monitor that may be used in place of a new SubMonitor
clearBlocked
public void clearBlocked()
-
Description copied from interface:
IProgressMonitorWithBlocking
- Clears the blocked state of the running operation. If a running
operation ever calls
setBlocked
, it must eventually call
clearBlocked
before the operation completes.
-
-
Specified by:
-
clearBlocked
in interface
IProgressMonitorWithBlocking
-
-
See Also:
-
IProgressMonitorWithBlocking.setBlocked(IStatus)
setBlocked
public void setBlocked(
IStatus reason)
-
Description copied from interface:
IProgressMonitorWithBlocking
- Indicates that this operation is blocked by some background activity. If
a running operation ever calls
setBlocked
, it must
eventually call clearBlocked
before the operation
completes.
If the caller is blocked by a currently executing job, this method will return
an IJobStatus
indicating the job that is currently blocking
the caller. If this blocking job is not known, this method will return a plain
informational IStatus
object.
-
-
Specified by:
-
setBlocked
in interface
IProgressMonitorWithBlocking
-
-
Parameters:
-
reason
- an optional status object whose message describes the
reason why this operation is blocked, or null
if this
information is not available. -
See Also:
-
IProgressMonitorWithBlocking.clearBlocked()
eq
protected static boolean eq(
Object o1,
Object o2)
-
-
Guidelines for using Eclipse APIs.
Copyright (c) Eclipse contributors and others 2000, 2008. All rights reserved.