blob: cd14c6ddd17b86f1be7f3a1357c17b3360203492 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.runtime.jobs;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
/**
* The job manager provides facilities for scheduling, querying, and maintaining jobs
* and locks. In particular, the job manager provides the following services:
* <ul>
* <li>Maintains a queue of jobs that are waiting to be run. Items can be added to
* the queue using the <code>schedule</code> method.</li>
* <li>Allows manipulation of groups of jobs called job families. Job families can
* be canceled, put to sleep, or woken up atomically. There is also a mechanism
* for querying the set of known jobs in a given family.</li>
* <li>Allows listeners to find out about progress on running jobs, and to find out
* when jobs have changed states.</li>
* <li>Provides a factory for creating lock objects. Lock objects are smart monitors
* that have strategies for avoiding deadlock.</li>
* <li>Provide feedback to a client that is waiting for a given job or family of jobs
* to complete.</li>
* </ul>
*
* @see Job
* @see ILock
* @since 3.0
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
public interface IJobManager {
/**
* A system property key indicating whether the job manager should create
* job threads as daemon threads. Set to <code>true</code> to force all worker
* threads to be created as daemon threads. Set to <code>false</code> to force
* all worker threads to be created as non-daemon threads.
* @since 3.3
*/
public static final String PROP_USE_DAEMON_THREADS = "eclipse.jobs.daemon"; //$NON-NLS-1$
/**
* Registers a job listener with the job manager.
* Has no effect if an identical listener is already registered.
*
* @param listener the listener to be added
* @see #removeJobChangeListener(IJobChangeListener)
* @see IJobChangeListener
*/
public void addJobChangeListener(IJobChangeListener listener);
/**
* Begins applying this rule in the calling thread. If the rule conflicts with another
* rule currently running in another thread, this method blocks until there are
* no conflicting rules. Calls to <tt>beginRule</tt> must eventually be followed
* by a matching call to <tt>endRule</tt> in the same thread and with the identical
* rule instance.
* <p>
* Rules can be nested only if the rule for the inner <tt>beginRule</tt>
* is contained within the rule for the outer <tt>beginRule</tt>. Rule containment
* is tested with the API method <tt>ISchedulingRule.contains</tt>. Also, begin/end
* pairs must be strictly nested. Only the rule that has most recently begun
* can be ended at any given time.
* <p>
* A rule of <code>null</code> can be used, but will be ignored for scheduling
* purposes. The outermost non-null rule in the thread will be used for scheduling. A
* <code>null</code> rule that is begun must still be ended.
* <p>
* If this method is called from within a job that has a scheduling rule, the
* given rule must also be contained within the rule for the running job.
* <p>
* Note that <tt>endRule</tt> must be called even if <tt>beginRule</tt> fails.
* The recommended usage is:
* <pre>
* final ISchedulingRule rule = ...;
* try {
* manager.beginRule(rule, monitor);
* } finally {
* manager.endRule(rule);
* }
* </pre>
*
* @param rule the rule to begin applying in this thread, or <code>null</code>
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
* @throws IllegalArgumentException if the rule is not strictly nested within
* all other rules currently active for this thread
* @throws OperationCanceledException if the supplied monitor reports cancelation
* before the rule becomes available
* @see ISchedulingRule#contains(ISchedulingRule)
*/
public void beginRule(ISchedulingRule rule, IProgressMonitor monitor);
/**
* Cancels all jobs in the given job family. Jobs in the family that are currently waiting
* will be removed from the queue. Sleeping jobs will be discarded without having
* a chance to wake up. Currently executing jobs will be asked to cancel but there
* is no guarantee that they will do so.
*
* @param family the job family to cancel, or <code>null</code> to cancel all jobs
* @see Job#belongsTo(Object)
*/
public void cancel(Object family);
/**
* Returns a progress monitor that can be used to provide
* aggregated progress feedback on a set of running jobs. A user
* interface will typically group all jobs in a progress group together,
* providing progress feedback for individual jobs as well as aggregated
* progress for the entire group. Jobs in the group may be run sequentially,
* in parallel, or some combination of the two.
* <p>
* Recommended usage (this snippet runs two jobs in sequence in a
* single progress group):
* <pre>
* Job parseJob, compileJob;
* IProgressMonitor pm = Platform.getJobManager().createProgressGroup();
* try {
* pm.beginTask("Building", 10);
* parseJob.setProgressGroup(pm, 5);
* parseJob.schedule();
* compileJob.setProgressGroup(pm, 5);
* compileJob.schedule();
* parseJob.join();
* compileJob.join();
* } finally {
* pm.done();
* }
* </pre>
*
* @see Job#setProgressGroup(IProgressMonitor, int)
* @see IProgressMonitor
* @return a progress monitor
*/
public IProgressMonitor createProgressGroup();
/**
* Returns the scheduling rule currently held by this thread, or <code>null</code>
* if the current thread does not hold any scheduling rule.
* <p>
* If this method is called from within the scope of a running job with a non-null
* scheduling rule, then this method is equivalent to calling <code>currentJob().getRule()</code>.
* Otherwise, this method will return the first scheduling rule obtained by this
* thread via {@link #beginRule(ISchedulingRule, IProgressMonitor)} that has not
* yet had a corresponding call to {@link #endRule(ISchedulingRule)}.
* </p>
*
* @return the current rule or <code>null</code>
* @since 3.5
*/
public ISchedulingRule currentRule();
/**
* Returns the job that is currently running in this thread, or <code>null</code> if there
* is no currently running job.
*
* @return the job or <code>null</code>
*/
public Job currentJob();
/**
* Ends the application of a rule to the calling thread. Calls to <tt>endRule</tt>
* must be preceded by a matching call to <tt>beginRule</tt> in the same thread
* with an identical rule instance.
* <p>
* Rules can be nested only if the rule for the inner <tt>beginRule</tt>
* is contained within the rule for the outer <tt>beginRule</tt>. Also, begin/end
* pairs must be strictly nested. Only the rule that has most recently begun
* can be ended at any given time.
*
* @param rule the rule to end applying in this thread
* @throws IllegalArgumentException if this method is called on a rule for which
* there is no matching begin, or that does not match the most recent begin.
* @see ISchedulingRule#contains(ISchedulingRule)
*/
public void endRule(ISchedulingRule rule);
/**
* Returns all waiting, executing and sleeping jobs belonging
* to the given family. If no jobs are found, an empty array is returned.
*
* @param family the job family to find, or <code>null</code> to find all jobs
* @return the job array
* @see Job#belongsTo(Object)
*/
public Job[] find(Object family);
/**
* Returns whether the job manager is currently idle. The job manager is
* idle if no jobs are currently running or waiting to run.
*
* @return <code>true</code> if the job manager is idle, and
* <code>false</code> otherwise
* @since 3.1
*/
public boolean isIdle();
/**
* Returns whether the job manager is currently suspended.
*
* @return <code>true</code> if the job manager is suspended, and
* <code>false</code> otherwise
* @since 3.4
* @see #suspend()
* @see #resume()
*/
public boolean isSuspended();
/**
* Waits until all jobs of the given family are finished. This method will block the
* calling thread until all such jobs have finished executing, or until this thread is
* interrupted. If there are no jobs in the family that are currently waiting, running,
* or sleeping, this method returns immediately. Feedback on how the join is
* progressing is provided to a progress monitor.
* <p>
* If this method is called while the job manager is suspended, only jobs
* that are currently running will be joined; Once there are no jobs
* in the family in the {@link Job#RUNNING} state, this method returns.
* </p>
* <p>
* Note that there is a deadlock risk when using join. If the calling thread owns
* a lock or object monitor that the joined thread is waiting for, deadlock
* will occur. This method can also result in starvation of the current thread if
* another thread continues to add jobs of the given family, or if a
* job in the given family reschedules itself in an infinite loop.
* </p>
*
* @param family the job family to join, or <code>null</code> to join all jobs.
* @param monitor Progress monitor for reporting progress on how the
* wait is progressing, or <code>null</code> if no progress monitoring is required.
* @exception InterruptedException if this thread is interrupted while waiting
* @exception OperationCanceledException if the progress monitor is canceled while waiting
* @see Job#belongsTo(Object)
* @see #suspend()
*/
public void join(Object family, IProgressMonitor monitor) throws InterruptedException, OperationCanceledException;
/**
* Creates a new lock object. All lock objects supplied by the job manager
* know about each other and will always avoid circular deadlock amongst
* themselves.
*
* @return the new lock object
*/
public ILock newLock();
/**
* Removes a job listener from the job manager.
* Has no effect if an identical listener is not already registered.
*
* @param listener the listener to be removed
* @see #addJobChangeListener(IJobChangeListener)
* @see IJobChangeListener
*/
public void removeJobChangeListener(IJobChangeListener listener);
/**
* Resumes execution of jobs after a previous <code>suspend</code>. All
* jobs that were sleeping or waiting prior to the suspension, or that were
* scheduled while the job manager was suspended, will now be eligible
* for execution.
* <p>
* Calling this method on a rule that is not suspended has no effect. If another
* thread also owns the rule at the time this method is called, then the rule will
* not be resumed until all threads have released the rule.
*
* @deprecated This method is not safe and should not be used.
* Suspending a scheduling rule violates the thread safety
* of clients that use scheduling rules as a mutual exclusion mechanism,
* and can result in concurrency problems in all clients that use the suspended rule.
* @see #suspend(ISchedulingRule, IProgressMonitor)
*/
public void resume(ISchedulingRule rule);
/**
* Resumes execution of jobs after a previous <code>suspend</code>. All
* jobs that were sleeping or waiting prior to the suspension, or that were
* scheduled while the job manager was suspended, will now be eligible
* for execution.
* <p>
* Calling <code>resume</code> when the job manager is not suspended
* has no effect.
*
* @see #suspend()
* @see #isSuspended()
*/
public void resume();
/**
* Provides a hook that is notified whenever a thread is about to wait on a lock,
* or when a thread is about to release a lock. This hook must only be set once.
* <p>
* This method is for internal use by the platform-related plug-ins.
* Clients should not call this method.
* </p>
* @see LockListener
*/
public void setLockListener(LockListener listener);
/**
* Registers a progress provider with the job manager. If there was a
* provider already registered, it is replaced.
* <p>
* This method is intended for use by the currently executing Eclipse application.
* Plug-ins outside the currently running application should not call this method.
* </p>
*
* @param provider the new provider, or <code>null</code> if no progress
* is needed
*/
public void setProgressProvider(ProgressProvider provider);
/**
* Suspends execution of all jobs. Jobs that are already running
* when this method is invoked will complete as usual, but all sleeping and
* waiting jobs will not be executed until the job manager is resumed.
* <p>
* The job manager will remain suspended until a subsequent call to
* <code>resume</code>. Further calls to <code>suspend</code>
* when the job manager is already suspended are ignored.
* <p>
* All attempts to join sleeping and waiting jobs while the job manager is
* suspended will return immediately.
* <p>
* Note that this very powerful function should be used with extreme caution.
* Suspending the job manager will prevent all jobs in the system from executing,
* which may have adverse affects on components that are relying on
* execution of jobs. The job manager should never be suspended without intent
* to resume execution soon afterwards.
*
* @see #resume()
* @see #join(Object, IProgressMonitor)
* @see #isSuspended()
*/
public void suspend();
/**
* Defers execution of all jobs with scheduling rules that conflict with the
* given rule. The caller will be blocked until all currently executing jobs with
* conflicting rules are completed. Conflicting jobs that are sleeping or waiting at
* the time this method is called will not be executed until the rule is resumed.
* <p>
* While a rule is suspended, all calls to <code>beginRule</code> and
* <code>endRule</code> on a suspended rule will not block the caller.
* The rule remains suspended until a subsequent call to
* <code>resume(ISchedulingRule)</code> with the identical rule instance.
* Further calls to <code>suspend</code> with an identical rule prior to calling
* <code>resume</code> are ignored.
* </p>
* <p>
* This method is long-running; progress and cancelation are provided by
* the given progress monitor. In the case of cancelation, the rule will
* not be suspended.
* </p>
* Note: this very powerful function should be used with extreme caution.
* Suspending rules will prevent jobs in the system from executing, which may
* have adverse effects on components that are relying on execution of jobs.
* The job manager should never be suspended without intent to resume
* execution soon afterwards. Deadlock will result if the thread responsible
* for resuming the rule attempts to join a suspended job.
*
* @deprecated This method is not safe and should not be used.
* Suspending a scheduling rule violates the thread safety
* of clients that use scheduling rules as a mutual exclusion mechanism,
* and can result in concurrency problems in all clients that use the suspended rule.
* @param rule The scheduling rule to suspend. Must not be <code>null</code>.
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting is not desired
* @exception OperationCanceledException if the operation is canceled.
* Cancelation can occur even if no progress monitor is provided.
* @see #resume(ISchedulingRule)
*/
public void suspend(ISchedulingRule rule, IProgressMonitor monitor);
/**
* Requests that all jobs in the given job family be suspended. Jobs currently
* waiting to be run will be removed from the queue and moved into the
* <code>SLEEPING</code> state. Jobs that have been put to sleep
* will remain in that state until either resumed or canceled. This method has
* no effect on jobs that are not currently waiting to be run.
* <p>
* Sleeping jobs can be resumed using <code>wakeUp</code>.
*
* @param family the job family to sleep, or <code>null</code> to sleep all jobs.
* @see Job#belongsTo(Object)
*/
public void sleep(Object family);
/**
* Transfers ownership of a scheduling rule to another thread. The identical
* scheduling rule must currently be owned by the calling thread as a result of
* a previous call to <code>beginRule</code>. The destination thread must
* not already own a scheduling rule.
* <p>
* Calling this method is equivalent to atomically calling <code>endRule</code>
* in the calling thread followed by an immediate <code>beginRule</code> in
* the destination thread. The destination thread is responsible for subsequently
* calling <code>endRule</code> when it is finished using the rule.
* <p>
* This method has no effect when the destination thread is the same as the
* calling thread.
*
* @param rule The scheduling rule to transfer
* @param destinationThread The new owner for the transferred rule.
* @since 3.1
*/
public void transferRule(ISchedulingRule rule, Thread destinationThread);
/**
* Resumes scheduling of all sleeping jobs in the given family. This method
* has no effect on jobs in the family that are not currently sleeping.
*
* @param family the job family to wake up, or <code>null</code> to wake up all jobs
* @see Job#belongsTo(Object)
*/
public void wakeUp(Object family);
}