Mercurial > projects > dwt-addons
diff dwtx/core/runtime/jobs/Job.d @ 122:9d0585bcb7aa
Add core.jobs package
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 12 Aug 2008 02:34:21 +0200 |
parents | |
children | 862b05e0334a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/core/runtime/jobs/Job.d Tue Aug 12 02:34:21 2008 +0200 @@ -0,0 +1,699 @@ +/******************************************************************************* + * Copyright (c) 2003, 2007 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.core.runtime.jobs.Job; + +import tango.core.Thread; +import dwt.dwthelper.utils; + +import dwtx.core.internal.jobs.InternalJob; +import dwtx.core.internal.jobs.JobManager; +import dwtx.core.runtime.IAdaptable; +import dwtx.core.runtime.IProgressMonitor; +import dwtx.core.runtime.IStatus; +import dwtx.core.runtime.QualifiedName; +import dwtx.core.runtime.Status; +import dwtx.core.runtime.jobs.IJobManager; +import dwtx.core.runtime.jobs.IJobChangeListener; +import dwtx.core.runtime.jobs.ISchedulingRule; + +/** + * Jobs are units of runnable work that can be scheduled to be run with the job + * manager. Once a job has completed, it can be scheduled to run again (jobs are + * reusable). + * <p> + * Jobs have a state that indicates what they are currently doing. When constructed, + * jobs start with a state value of <code>NONE</code>. When a job is scheduled + * to be run, it moves into the <code>WAITING</code> state. When a job starts + * running, it moves into the <code>RUNNING</code> state. When execution finishes + * (either normally or through cancelation), the state changes back to + * <code>NONE</code>. + * </p><p> + * A job can also be in the <code>SLEEPING</code> state. This happens if a user + * calls Job.sleep() on a waiting job, or if a job is scheduled to run after a specified + * delay. Only jobs in the <code>WAITING</code> state can be put to sleep. + * Sleeping jobs can be woken at any time using Job.wakeUp(), which will put the + * job back into the <code>WAITING</code> state. + * </p><p> + * Jobs can be assigned a priority that is used as a hint about how the job should + * be scheduled. There is no guarantee that jobs of one priority will be run before + * all jobs of lower priority. The javadoc for the various priority constants provide + * more detail about what each priority means. By default, jobs start in the + * <code>LONG</code> priority class. + * + * @see IJobManager + * @since 3.0 + */ +public abstract class Job : InternalJob, IAdaptable { + // DWT from IAdaptable + public Object getAdapter(ClassInfo adapter){ + return super.getAdapter(adapter); + } + + /** + * Job status return value that is used to indicate asynchronous job completion. + * @see Job#run(IProgressMonitor) + * @see Job#done(IStatus) + */ + private static IStatus ASYNC_FINISH_; + public static IStatus ASYNC_FINISH(){ + if( ASYNC_FINISH_ is null ){ + synchronized( Job.classinfo ) { + if( ASYNC_FINISH_ is null ){ + ASYNC_FINISH_ = new Status(IStatus.OK, JobManager.PI_JOBS, 1, "", null);//$NON-NLS-1$ + } + } + } + return ASYNC_FINISH_; + } + + /* Job priorities */ + /** + * Job priority constant (value 10) for interactive jobs. + * Interactive jobs generally have priority over all other jobs. + * Interactive jobs should be either fast running or very low on CPU + * usage to avoid blocking other interactive jobs from running. + * + * @see #getPriority() + * @see #setPriority(int) + * @see #run(IProgressMonitor) + */ + public static const int INTERACTIVE = 10; + /** + * Job priority constant (value 20) for short background jobs. + * Short background jobs are jobs that typically complete within a second, + * but may take longer in some cases. Short jobs are given priority + * over all other jobs except interactive jobs. + * + * @see #getPriority() + * @see #setPriority(int) + * @see #run(IProgressMonitor) + */ + public static const int SHORT = 20; + /** + * Job priority constant (value 30) for long-running background jobs. + * + * @see #getPriority() + * @see #setPriority(int) + * @see #run(IProgressMonitor) + */ + public static const int LONG = 30; + /** + * Job priority constant (value 40) for build jobs. Build jobs are + * generally run after all other background jobs complete. + * + * @see #getPriority() + * @see #setPriority(int) + * @see #run(IProgressMonitor) + */ + public static const int BUILD = 40; + + /** + * Job priority constant (value 50) for decoration jobs. + * Decoration jobs have lowest priority. Decoration jobs generally + * compute extra information that the user may be interested in seeing + * but is generally not waiting for. + * + * @see #getPriority() + * @see #setPriority(int) + * @see #run(IProgressMonitor) + */ + public static const int DECORATE = 50; + /** + * Job state code (value 0) indicating that a job is not + * currently sleeping, waiting, or running (i.e., the job manager doesn't know + * anything about the job). + * + * @see #getState() + */ + public static const int NONE = 0; + /** + * Job state code (value 1) indicating that a job is sleeping. + * + * @see #run(IProgressMonitor) + * @see #getState() + */ + public static const int SLEEPING = 0x01; + /** + * Job state code (value 2) indicating that a job is waiting to be run. + * + * @see #getState() + */ + public static const int WAITING = 0x02; + /** + * Job state code (value 4) indicating that a job is currently running + * + * @see #getState() + */ + public static const int RUNNING = 0x04; + + /** + * Returns the job manager. + * + * @return the job manager + * @since dwtx.core.jobs 3.2 + */ + public static final IJobManager getJobManager() { + return manager; + } + + /** + * Creates a new job with the specified name. The job name is a human-readable + * value that is displayed to users. The name does not need to be unique, but it + * must not be <code>null</code>. + * + * @param name the name of the job. + */ + public this(String name) { + super(name); + } + + /** + * Registers a job listener with this job + * Has no effect if an identical listener is already registered. + * + * @param listener the listener to be added. + */ + public final void addJobChangeListener(IJobChangeListener listener) { + super.addJobChangeListener(listener); + } + + /** + * Returns whether this job belongs to the given family. Job families are + * represented as objects that are not interpreted or specified in any way + * by the job manager. Thus, a job can choose to belong to any number of + * families. + * <p> + * Clients may override this method. This default implementation always returns + * <code>false</code>. Overriding implementations must return <code>false</code> + * for families they do not recognize. + * </p> + * + * @param family the job family identifier + * @return <code>true</code> if this job belongs to the given family, and + * <code>false</code> otherwise. + */ + public bool belongsTo(Object family) { + return false; + } + + /** + * Stops the job. If the job is currently waiting, + * it will be removed from the queue. If the job is sleeping, + * it will be discarded without having a chance to resume and its sleeping state + * will be cleared. If the job is currently executing, it will be asked to + * stop but there is no guarantee that it will do so. + * + * @return <code>false</code> if the job is currently running (and thus may not + * respond to cancelation), and <code>true</code> in all other cases. + */ + public final bool cancel() { + return super.cancel(); + } + + /** + * A hook method indicating that this job is running and {@link #cancel()} + * is being called for the first time. + * <p> + * Subclasses may override this method to perform additional work when + * a cancelation request is made. This default implementation does nothing. + * @since 3.3 + */ + protected void canceling() { + //default implementation does nothing + } + + /** + * Jobs that complete their execution asynchronously must indicate when they + * are finished by calling this method. This method must not be called by + * a job that has not indicated that it is executing asynchronously. + * <p> + * This method must not be called from within the scope of a job's <code>run</code> + * method. Jobs should normally indicate completion by returning an appropriate + * status from the <code>run</code> method. Jobs that return a status of + * <code>ASYNC_FINISH</code> from their run method must later call + * <code>done</code> to indicate completion. + * + * @param result a status object indicating the result of the job's execution. + * @see #ASYNC_FINISH + * @see #run(IProgressMonitor) + */ + public final void done(IStatus result) { + super.done(result); + } + + /** + * Returns the human readable name of this job. The name is never + * <code>null</code>. + * + * @return the name of this job + */ + public final String getName() { + return super.getName(); + } + + /** + * Returns the priority of this job. The priority is used as a hint when the job + * is scheduled to be run. + * + * @return the priority of the job. One of INTERACTIVE, SHORT, LONG, BUILD, + * or DECORATE. + */ + public final int getPriority() { + return super.getPriority(); + } + + /** + * Returns the value of the property of this job identified by the given key, + * or <code>null</code> if this job has no such property. + * + * @param key the name of the property + * @return the value of the property, + * or <code>null</code> if this job has no such property + * @see #setProperty(QualifiedName, Object) + */ + public final Object getProperty(QualifiedName key) { + return super.getProperty(key); + } + + /** + * Returns the result of this job's last run. + * + * @return the result of this job's last run, or <code>null</code> if this + * job has never finished running. + */ + public final IStatus getResult() { + return super.getResult(); + } + + /** + * Returns the scheduling rule for this job. Returns <code>null</code> if this job has no + * scheduling rule. + * + * @return the scheduling rule for this job, or <code>null</code>. + * @see ISchedulingRule + * @see #setRule(ISchedulingRule) + */ + public final ISchedulingRule getRule() { + return super.getRule(); + } + + /** + * Returns the state of the job. Result will be one of: + * <ul> + * <li><code>Job.RUNNING</code> - if the job is currently running.</li> + * <li><code>Job.WAITING</code> - if the job is waiting to be run.</li> + * <li><code>Job.SLEEPING</code> - if the job is sleeping.</li> + * <li><code>Job.NONE</code> - in all other cases.</li> + * </ul> + * <p> + * Note that job state is inherently volatile, and in most cases clients + * cannot rely on the result of this method being valid by the time the + * result is obtained. For example, if <tt>getState</tt> returns + * <tt>RUNNING</tt>, the job may have actually completed by the + * time the <tt>getState</tt> method returns. All clients can infer from + * invoking this method is that the job was recently in the returned state. + * + * @return the job state + */ + public final int getState() { + return super.getState(); + } + + /** + * Returns the thread that this job is currently running in. + * + * @return the thread this job is running in, or <code>null</code> + * if this job is not running or the thread is unknown. + */ + public final Thread getThread() { + return super.getThread(); + } + + /** + * Returns whether this job is blocking a higher priority non-system job from + * starting due to a conflicting scheduling rule. Returns <code>false</code> + * if this job is not running, or is not blocking a higher priority non-system job. + * + * @return <code>true</code> if this job is blocking a higher priority non-system + * job, and <code>false</code> otherwise. + * @see #getRule() + * @see #isSystem() + */ + public final bool isBlocking() { + return super.isBlocking(); + } + + /** + * Returns whether this job is a system job. System jobs are typically not + * revealed to users in any UI presentation of jobs. Other than their UI presentation, + * system jobs act exactly like other jobs. If this value is not explicitly set, jobs + * are treated as non-system jobs. The default value is <code>false</code>. + * + * @return <code>true</code> if this job is a system job, and + * <code>false</code> otherwise. + * @see #setSystem(bool) + */ + public final bool isSystem() { + return super.isSystem(); + } + + /** + * Returns whether this job has been directly initiated by a UI end user. + * These jobs may be presented differently in the UI. The default value + * is <code>false</code>. + * + * @return <code>true</code> if this job is a user-initiated job, and + * <code>false</code> otherwise. + * @see #setUser(bool) + */ + public final bool isUser() { + return super.isUser(); + } + + /** + * Waits until this job is finished. This method will block the calling thread until the + * job has finished executing, or until this thread has been interrupted. If the job + * has not been scheduled, this method returns immediately. A job must not + * be joined from within the scope of its run method. + * <p> + * If this method is called on a job that reschedules itself from within the + * <tt>run</tt> method, the join will return at the end of the first execution. + * In other words, join will return the first time this job exits the + * {@link #RUNNING} state, or as soon as this job enters the {@link #NONE} state. + * </p> + * <p> + * If this method is called while the job manager is suspended, this job + * will only be joined if it is already running; if this job is waiting or sleeping, + * this method returns immediately. + * </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. + * </p> + * + * @exception InterruptedException if this thread is interrupted while waiting + * @see ILock + * @see IJobManager#suspend() + */ + public final void join() { + super.join(); + } + + /** + * Removes a job listener from this job. + * Has no effect if an identical listener is not already registered. + * + * @param listener the listener to be removed + */ + public final void removeJobChangeListener(IJobChangeListener listener) { + super.removeJobChangeListener(listener); + } + + /** + * Executes this job. Returns the result of the execution. + * <p> + * The provided monitor can be used to report progress and respond to + * cancellation. If the progress monitor has been canceled, the job + * should finish its execution at the earliest convenience and return a result + * status of severity {@link IStatus#CANCEL}. The singleton + * cancel status {@link Status#CANCEL_STATUS} can be used for + * this purpose. The monitor is only valid for the duration of the invocation + * of this method. + * <p> + * This method must not be called directly by clients. Clients should call + * <code>schedule</code>, which will in turn cause this method to be called. + * <p> + * Jobs can optionally finish their execution asynchronously (in another thread) by + * returning a result status of {@link #ASYNC_FINISH}. Jobs that finish + * asynchronously <b>must</b> specify the execution thread by calling + * <code>setThread</code>, and must indicate when they are finished by calling + * the method <code>done</code>. + * + * @param monitor the monitor to be used for reporting progress and + * responding to cancelation. The monitor is never <code>null</code> + * @return resulting status of the run. The result must not be <code>null</code> + * @see #ASYNC_FINISH + * @see #done(IStatus) + */ + protected abstract IStatus run(IProgressMonitor monitor); + + /** + * Schedules this job to be run. The job is added to a queue of waiting + * jobs, and will be run when it arrives at the beginning of the queue. + * <p> + * This is a convenience method, fully equivalent to + * <code>schedule(0L)</code>. + * </p> + * @see #schedule(long) + */ + public final void schedule() { + super.schedule(0L); + } + + /** + * Schedules this job to be run after a specified delay. The job is put in the + * {@link #SLEEPING} state until the specified delay has elapsed, after which + * the job is added to a queue of {@link #WAITING} jobs. Once the job arrives + * at the beginning of the queue, it will be run at the first available opportunity. + * </p><p> + * Jobs of equal priority and <code>delay</code> with conflicting scheduling + * rules are guaranteed to run in the order they are scheduled. No guarantees + * are made about the relative execution order of jobs with unrelated or + * <code>null</code> scheduling rules, or different priorities. + * <p> + * If this job is currently running, it will be rescheduled with the specified + * delay as soon as it finishes. If this method is called multiple times + * while the job is running, the job will still only be rescheduled once, + * with the most recent delay value that was provided. + * </p><p> + * Scheduling a job that is waiting or sleeping has no effect. + * </p> + * + * @param delay a time delay in milliseconds before the job should run + * @see ISchedulingRule + */ + public final void schedule(long delay) { + super.schedule(delay); + } + + /** + * Changes the name of this job. If the job is currently running, waiting, + * or sleeping, the new job name may not take effect until the next time the + * job is scheduled. + * <p> + * The job name is a human-readable value that is displayed to users. The name + * does not need to be unique, but it must not be <code>null</code>. + * + * @param name the name of the job. + */ + public final void setName(String name) { + super.setName(name); + } + + /** + * Sets the priority of the job. This will not affect the execution of + * a running job, but it will affect how the job is scheduled while + * it is waiting to be run. + * + * @param priority the new job priority. One of + * INTERACTIVE, SHORT, LONG, BUILD, or DECORATE. + */ + public final void setPriority(int priority) { + super.setPriority(priority); + } + + /** + * Associates this job with a progress group. Progress feedback + * on this job's next execution will be displayed together with other + * jobs in that group. The provided monitor must be a monitor + * created by the method <tt>IJobManager.createProgressGroup</tt> + * and must have at least <code>ticks</code> units of available work. + * <p> + * The progress group must be set before the job is scheduled. + * The group will be used only for a single invocation of the job's + * <tt>run</tt> method, after which any association of this job to the + * group will be lost. + * + * @see IJobManager#createProgressGroup() + * @param group The progress group to use for this job + * @param ticks the number of work ticks allocated from the + * parent monitor, or {@link IProgressMonitor#UNKNOWN} + */ + public final void setProgressGroup(IProgressMonitor group, int ticks) { + super.setProgressGroup(group, ticks); + } + + /** + * Sets the value of the property of this job identified + * by the given key. If the supplied value is <code>null</code>, + * the property is removed from this resource. + * <p> + * Properties are intended to be used as a caching mechanism + * by ISV plug-ins. They allow key-object associations to be stored with + * a job instance. These key-value associations are maintained in + * memory (at all times), and the information is never discarded automatically. + * </p><p> + * The qualifier part of the property name must be the unique identifier + * of the declaring plug-in (e.g. <code>"com.example.plugin"</code>). + * </p> + * + * @param key the qualified name of the property + * @param value the value of the property, + * or <code>null</code> if the property is to be removed + * @see #getProperty(QualifiedName) + */ + public void setProperty(QualifiedName key, Object value) { + super.setProperty(key, value); + } + + /** + * Sets the scheduling rule to be used when scheduling this job. This method + * must be called before the job is scheduled. + * + * @param rule the new scheduling rule, or <code>null</code> if the job + * should have no scheduling rule + * @see #getRule() + */ + public final void setRule(ISchedulingRule rule) { + super.setRule(rule); + } + + /** + * Sets whether or not this job is a system job. System jobs are typically not + * revealed to users in any UI presentation of jobs. Other than their UI presentation, + * system jobs act exactly like other jobs. If this value is not explicitly set, jobs + * are treated as non-system jobs. This method must be called before the job + * is scheduled. + * + * @param value <code>true</code> if this job should be a system job, and + * <code>false</code> otherwise. + * @see #isSystem() + */ + public final void setSystem(bool value) { + super.setSystem(value); + } + + /** + * Sets whether or not this job has been directly initiated by a UI end user. + * These jobs may be presented differently in the UI. This method must be + * called before the job is scheduled. + * + * @param value <code>true</code> if this job is a user-initiated job, and + * <code>false</code> otherwise. + * @see #isUser() + */ + public final void setUser(bool value) { + super.setUser(value); + } + + /** + * Sets the thread that this job is currently running in, or <code>null</code> + * if this job is not running or the thread is unknown. + * <p> + * Jobs that use the {@link #ASYNC_FINISH} return code should tell + * the job what thread it is running in. This is used to prevent deadlocks. + * + * @param thread the thread that this job is running in. + * + * @see #ASYNC_FINISH + * @see #run(IProgressMonitor) + */ + public final void setThread(Thread thread) { + super.setThread(thread); + } + + /** + * Returns whether this job should be run. + * If <code>false</code> is returned, this job will be discarded by the job manager + * without running. + * <p> + * This method is called immediately prior to calling the job's + * run method, so it can be used for last minute pre-condition checking before + * a job is run. This method must not attempt to schedule or change the + * state of any other job. + * </p><p> + * Clients may override this method. This default implementation always returns + * <code>true</code>. + * </p> + * + * @return <code>true</code> if this job should be run + * and <code>false</code> otherwise + */ + public bool shouldRun() { + return true; + } + + /** + * Returns whether this job should be scheduled. + * If <code>false</code> is returned, this job will be discarded by the job manager + * without being added to the queue. + * <p> + * This method is called immediately prior to adding the job to the waiting job + * queue.,so it can be used for last minute pre-condition checking before + * a job is scheduled. + * </p><p> + * Clients may override this method. This default implementation always returns + * <code>true</code>. + * </p> + * + * @return <code>true</code> if the job manager should schedule this job + * and <code>false</code> otherwise + */ + public bool shouldSchedule() { + return true; + } + + /** + * Requests that this job be suspended. If the job is currently waiting to be run, it + * will be removed from the queue move into the {@link #SLEEPING} state. + * The job will remain asleep until either resumed or canceled. If this job is not + * currently waiting to be run, this method has no effect. + * <p> + * Sleeping jobs can be resumed using <code>wakeUp</code>. + * + * @return <code>false</code> if the job is currently running (and thus cannot + * be put to sleep), and <code>true</code> in all other cases + * @see #wakeUp() + */ + public final bool sleep() { + return super.sleep(); + } + + /** + * Puts this job immediately into the {@link #WAITING} state so that it is + * eligible for immediate execution. If this job is not currently sleeping, + * the request is ignored. + * <p> + * This is a convenience method, fully equivalent to + * <code>wakeUp(0L)</code>. + * </p> + * @see #sleep() + */ + public final void wakeUp() { + super.wakeUp(0L); + } + + /** + * Puts this job back into the {@link #WAITING} state after + * the specified delay. This is equivalent to canceling the sleeping job and + * rescheduling with the given delay. If this job is not currently sleeping, + * the request is ignored. + * + * @param delay the number of milliseconds to delay + * @see #sleep() + */ + public final void wakeUp(long delay) { + super.wakeUp(delay); + } +}