comparison 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
comparison
equal deleted inserted replaced
121:c0304616ea23 122:9d0585bcb7aa
1 /*******************************************************************************
2 * Copyright (c) 2003, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module dwtx.core.runtime.jobs.Job;
14
15 import tango.core.Thread;
16 import dwt.dwthelper.utils;
17
18 import dwtx.core.internal.jobs.InternalJob;
19 import dwtx.core.internal.jobs.JobManager;
20 import dwtx.core.runtime.IAdaptable;
21 import dwtx.core.runtime.IProgressMonitor;
22 import dwtx.core.runtime.IStatus;
23 import dwtx.core.runtime.QualifiedName;
24 import dwtx.core.runtime.Status;
25 import dwtx.core.runtime.jobs.IJobManager;
26 import dwtx.core.runtime.jobs.IJobChangeListener;
27 import dwtx.core.runtime.jobs.ISchedulingRule;
28
29 /**
30 * Jobs are units of runnable work that can be scheduled to be run with the job
31 * manager. Once a job has completed, it can be scheduled to run again (jobs are
32 * reusable).
33 * <p>
34 * Jobs have a state that indicates what they are currently doing. When constructed,
35 * jobs start with a state value of <code>NONE</code>. When a job is scheduled
36 * to be run, it moves into the <code>WAITING</code> state. When a job starts
37 * running, it moves into the <code>RUNNING</code> state. When execution finishes
38 * (either normally or through cancelation), the state changes back to
39 * <code>NONE</code>.
40 * </p><p>
41 * A job can also be in the <code>SLEEPING</code> state. This happens if a user
42 * calls Job.sleep() on a waiting job, or if a job is scheduled to run after a specified
43 * delay. Only jobs in the <code>WAITING</code> state can be put to sleep.
44 * Sleeping jobs can be woken at any time using Job.wakeUp(), which will put the
45 * job back into the <code>WAITING</code> state.
46 * </p><p>
47 * Jobs can be assigned a priority that is used as a hint about how the job should
48 * be scheduled. There is no guarantee that jobs of one priority will be run before
49 * all jobs of lower priority. The javadoc for the various priority constants provide
50 * more detail about what each priority means. By default, jobs start in the
51 * <code>LONG</code> priority class.
52 *
53 * @see IJobManager
54 * @since 3.0
55 */
56 public abstract class Job : InternalJob, IAdaptable {
57 // DWT from IAdaptable
58 public Object getAdapter(ClassInfo adapter){
59 return super.getAdapter(adapter);
60 }
61
62 /**
63 * Job status return value that is used to indicate asynchronous job completion.
64 * @see Job#run(IProgressMonitor)
65 * @see Job#done(IStatus)
66 */
67 private static IStatus ASYNC_FINISH_;
68 public static IStatus ASYNC_FINISH(){
69 if( ASYNC_FINISH_ is null ){
70 synchronized( Job.classinfo ) {
71 if( ASYNC_FINISH_ is null ){
72 ASYNC_FINISH_ = new Status(IStatus.OK, JobManager.PI_JOBS, 1, "", null);//$NON-NLS-1$
73 }
74 }
75 }
76 return ASYNC_FINISH_;
77 }
78
79 /* Job priorities */
80 /**
81 * Job priority constant (value 10) for interactive jobs.
82 * Interactive jobs generally have priority over all other jobs.
83 * Interactive jobs should be either fast running or very low on CPU
84 * usage to avoid blocking other interactive jobs from running.
85 *
86 * @see #getPriority()
87 * @see #setPriority(int)
88 * @see #run(IProgressMonitor)
89 */
90 public static const int INTERACTIVE = 10;
91 /**
92 * Job priority constant (value 20) for short background jobs.
93 * Short background jobs are jobs that typically complete within a second,
94 * but may take longer in some cases. Short jobs are given priority
95 * over all other jobs except interactive jobs.
96 *
97 * @see #getPriority()
98 * @see #setPriority(int)
99 * @see #run(IProgressMonitor)
100 */
101 public static const int SHORT = 20;
102 /**
103 * Job priority constant (value 30) for long-running background jobs.
104 *
105 * @see #getPriority()
106 * @see #setPriority(int)
107 * @see #run(IProgressMonitor)
108 */
109 public static const int LONG = 30;
110 /**
111 * Job priority constant (value 40) for build jobs. Build jobs are
112 * generally run after all other background jobs complete.
113 *
114 * @see #getPriority()
115 * @see #setPriority(int)
116 * @see #run(IProgressMonitor)
117 */
118 public static const int BUILD = 40;
119
120 /**
121 * Job priority constant (value 50) for decoration jobs.
122 * Decoration jobs have lowest priority. Decoration jobs generally
123 * compute extra information that the user may be interested in seeing
124 * but is generally not waiting for.
125 *
126 * @see #getPriority()
127 * @see #setPriority(int)
128 * @see #run(IProgressMonitor)
129 */
130 public static const int DECORATE = 50;
131 /**
132 * Job state code (value 0) indicating that a job is not
133 * currently sleeping, waiting, or running (i.e., the job manager doesn't know
134 * anything about the job).
135 *
136 * @see #getState()
137 */
138 public static const int NONE = 0;
139 /**
140 * Job state code (value 1) indicating that a job is sleeping.
141 *
142 * @see #run(IProgressMonitor)
143 * @see #getState()
144 */
145 public static const int SLEEPING = 0x01;
146 /**
147 * Job state code (value 2) indicating that a job is waiting to be run.
148 *
149 * @see #getState()
150 */
151 public static const int WAITING = 0x02;
152 /**
153 * Job state code (value 4) indicating that a job is currently running
154 *
155 * @see #getState()
156 */
157 public static const int RUNNING = 0x04;
158
159 /**
160 * Returns the job manager.
161 *
162 * @return the job manager
163 * @since dwtx.core.jobs 3.2
164 */
165 public static final IJobManager getJobManager() {
166 return manager;
167 }
168
169 /**
170 * Creates a new job with the specified name. The job name is a human-readable
171 * value that is displayed to users. The name does not need to be unique, but it
172 * must not be <code>null</code>.
173 *
174 * @param name the name of the job.
175 */
176 public this(String name) {
177 super(name);
178 }
179
180 /**
181 * Registers a job listener with this job
182 * Has no effect if an identical listener is already registered.
183 *
184 * @param listener the listener to be added.
185 */
186 public final void addJobChangeListener(IJobChangeListener listener) {
187 super.addJobChangeListener(listener);
188 }
189
190 /**
191 * Returns whether this job belongs to the given family. Job families are
192 * represented as objects that are not interpreted or specified in any way
193 * by the job manager. Thus, a job can choose to belong to any number of
194 * families.
195 * <p>
196 * Clients may override this method. This default implementation always returns
197 * <code>false</code>. Overriding implementations must return <code>false</code>
198 * for families they do not recognize.
199 * </p>
200 *
201 * @param family the job family identifier
202 * @return <code>true</code> if this job belongs to the given family, and
203 * <code>false</code> otherwise.
204 */
205 public bool belongsTo(Object family) {
206 return false;
207 }
208
209 /**
210 * Stops the job. If the job is currently waiting,
211 * it will be removed from the queue. If the job is sleeping,
212 * it will be discarded without having a chance to resume and its sleeping state
213 * will be cleared. If the job is currently executing, it will be asked to
214 * stop but there is no guarantee that it will do so.
215 *
216 * @return <code>false</code> if the job is currently running (and thus may not
217 * respond to cancelation), and <code>true</code> in all other cases.
218 */
219 public final bool cancel() {
220 return super.cancel();
221 }
222
223 /**
224 * A hook method indicating that this job is running and {@link #cancel()}
225 * is being called for the first time.
226 * <p>
227 * Subclasses may override this method to perform additional work when
228 * a cancelation request is made. This default implementation does nothing.
229 * @since 3.3
230 */
231 protected void canceling() {
232 //default implementation does nothing
233 }
234
235 /**
236 * Jobs that complete their execution asynchronously must indicate when they
237 * are finished by calling this method. This method must not be called by
238 * a job that has not indicated that it is executing asynchronously.
239 * <p>
240 * This method must not be called from within the scope of a job's <code>run</code>
241 * method. Jobs should normally indicate completion by returning an appropriate
242 * status from the <code>run</code> method. Jobs that return a status of
243 * <code>ASYNC_FINISH</code> from their run method must later call
244 * <code>done</code> to indicate completion.
245 *
246 * @param result a status object indicating the result of the job's execution.
247 * @see #ASYNC_FINISH
248 * @see #run(IProgressMonitor)
249 */
250 public final void done(IStatus result) {
251 super.done(result);
252 }
253
254 /**
255 * Returns the human readable name of this job. The name is never
256 * <code>null</code>.
257 *
258 * @return the name of this job
259 */
260 public final String getName() {
261 return super.getName();
262 }
263
264 /**
265 * Returns the priority of this job. The priority is used as a hint when the job
266 * is scheduled to be run.
267 *
268 * @return the priority of the job. One of INTERACTIVE, SHORT, LONG, BUILD,
269 * or DECORATE.
270 */
271 public final int getPriority() {
272 return super.getPriority();
273 }
274
275 /**
276 * Returns the value of the property of this job identified by the given key,
277 * or <code>null</code> if this job has no such property.
278 *
279 * @param key the name of the property
280 * @return the value of the property,
281 * or <code>null</code> if this job has no such property
282 * @see #setProperty(QualifiedName, Object)
283 */
284 public final Object getProperty(QualifiedName key) {
285 return super.getProperty(key);
286 }
287
288 /**
289 * Returns the result of this job's last run.
290 *
291 * @return the result of this job's last run, or <code>null</code> if this
292 * job has never finished running.
293 */
294 public final IStatus getResult() {
295 return super.getResult();
296 }
297
298 /**
299 * Returns the scheduling rule for this job. Returns <code>null</code> if this job has no
300 * scheduling rule.
301 *
302 * @return the scheduling rule for this job, or <code>null</code>.
303 * @see ISchedulingRule
304 * @see #setRule(ISchedulingRule)
305 */
306 public final ISchedulingRule getRule() {
307 return super.getRule();
308 }
309
310 /**
311 * Returns the state of the job. Result will be one of:
312 * <ul>
313 * <li><code>Job.RUNNING</code> - if the job is currently running.</li>
314 * <li><code>Job.WAITING</code> - if the job is waiting to be run.</li>
315 * <li><code>Job.SLEEPING</code> - if the job is sleeping.</li>
316 * <li><code>Job.NONE</code> - in all other cases.</li>
317 * </ul>
318 * <p>
319 * Note that job state is inherently volatile, and in most cases clients
320 * cannot rely on the result of this method being valid by the time the
321 * result is obtained. For example, if <tt>getState</tt> returns
322 * <tt>RUNNING</tt>, the job may have actually completed by the
323 * time the <tt>getState</tt> method returns. All clients can infer from
324 * invoking this method is that the job was recently in the returned state.
325 *
326 * @return the job state
327 */
328 public final int getState() {
329 return super.getState();
330 }
331
332 /**
333 * Returns the thread that this job is currently running in.
334 *
335 * @return the thread this job is running in, or <code>null</code>
336 * if this job is not running or the thread is unknown.
337 */
338 public final Thread getThread() {
339 return super.getThread();
340 }
341
342 /**
343 * Returns whether this job is blocking a higher priority non-system job from
344 * starting due to a conflicting scheduling rule. Returns <code>false</code>
345 * if this job is not running, or is not blocking a higher priority non-system job.
346 *
347 * @return <code>true</code> if this job is blocking a higher priority non-system
348 * job, and <code>false</code> otherwise.
349 * @see #getRule()
350 * @see #isSystem()
351 */
352 public final bool isBlocking() {
353 return super.isBlocking();
354 }
355
356 /**
357 * Returns whether this job is a system job. System jobs are typically not
358 * revealed to users in any UI presentation of jobs. Other than their UI presentation,
359 * system jobs act exactly like other jobs. If this value is not explicitly set, jobs
360 * are treated as non-system jobs. The default value is <code>false</code>.
361 *
362 * @return <code>true</code> if this job is a system job, and
363 * <code>false</code> otherwise.
364 * @see #setSystem(bool)
365 */
366 public final bool isSystem() {
367 return super.isSystem();
368 }
369
370 /**
371 * Returns whether this job has been directly initiated by a UI end user.
372 * These jobs may be presented differently in the UI. The default value
373 * is <code>false</code>.
374 *
375 * @return <code>true</code> if this job is a user-initiated job, and
376 * <code>false</code> otherwise.
377 * @see #setUser(bool)
378 */
379 public final bool isUser() {
380 return super.isUser();
381 }
382
383 /**
384 * Waits until this job is finished. This method will block the calling thread until the
385 * job has finished executing, or until this thread has been interrupted. If the job
386 * has not been scheduled, this method returns immediately. A job must not
387 * be joined from within the scope of its run method.
388 * <p>
389 * If this method is called on a job that reschedules itself from within the
390 * <tt>run</tt> method, the join will return at the end of the first execution.
391 * In other words, join will return the first time this job exits the
392 * {@link #RUNNING} state, or as soon as this job enters the {@link #NONE} state.
393 * </p>
394 * <p>
395 * If this method is called while the job manager is suspended, this job
396 * will only be joined if it is already running; if this job is waiting or sleeping,
397 * this method returns immediately.
398 * </p>
399 * <p>
400 * Note that there is a deadlock risk when using join. If the calling thread owns
401 * a lock or object monitor that the joined thread is waiting for, deadlock
402 * will occur.
403 * </p>
404 *
405 * @exception InterruptedException if this thread is interrupted while waiting
406 * @see ILock
407 * @see IJobManager#suspend()
408 */
409 public final void join() {
410 super.join();
411 }
412
413 /**
414 * Removes a job listener from this job.
415 * Has no effect if an identical listener is not already registered.
416 *
417 * @param listener the listener to be removed
418 */
419 public final void removeJobChangeListener(IJobChangeListener listener) {
420 super.removeJobChangeListener(listener);
421 }
422
423 /**
424 * Executes this job. Returns the result of the execution.
425 * <p>
426 * The provided monitor can be used to report progress and respond to
427 * cancellation. If the progress monitor has been canceled, the job
428 * should finish its execution at the earliest convenience and return a result
429 * status of severity {@link IStatus#CANCEL}. The singleton
430 * cancel status {@link Status#CANCEL_STATUS} can be used for
431 * this purpose. The monitor is only valid for the duration of the invocation
432 * of this method.
433 * <p>
434 * This method must not be called directly by clients. Clients should call
435 * <code>schedule</code>, which will in turn cause this method to be called.
436 * <p>
437 * Jobs can optionally finish their execution asynchronously (in another thread) by
438 * returning a result status of {@link #ASYNC_FINISH}. Jobs that finish
439 * asynchronously <b>must</b> specify the execution thread by calling
440 * <code>setThread</code>, and must indicate when they are finished by calling
441 * the method <code>done</code>.
442 *
443 * @param monitor the monitor to be used for reporting progress and
444 * responding to cancelation. The monitor is never <code>null</code>
445 * @return resulting status of the run. The result must not be <code>null</code>
446 * @see #ASYNC_FINISH
447 * @see #done(IStatus)
448 */
449 protected abstract IStatus run(IProgressMonitor monitor);
450
451 /**
452 * Schedules this job to be run. The job is added to a queue of waiting
453 * jobs, and will be run when it arrives at the beginning of the queue.
454 * <p>
455 * This is a convenience method, fully equivalent to
456 * <code>schedule(0L)</code>.
457 * </p>
458 * @see #schedule(long)
459 */
460 public final void schedule() {
461 super.schedule(0L);
462 }
463
464 /**
465 * Schedules this job to be run after a specified delay. The job is put in the
466 * {@link #SLEEPING} state until the specified delay has elapsed, after which
467 * the job is added to a queue of {@link #WAITING} jobs. Once the job arrives
468 * at the beginning of the queue, it will be run at the first available opportunity.
469 * </p><p>
470 * Jobs of equal priority and <code>delay</code> with conflicting scheduling
471 * rules are guaranteed to run in the order they are scheduled. No guarantees
472 * are made about the relative execution order of jobs with unrelated or
473 * <code>null</code> scheduling rules, or different priorities.
474 * <p>
475 * If this job is currently running, it will be rescheduled with the specified
476 * delay as soon as it finishes. If this method is called multiple times
477 * while the job is running, the job will still only be rescheduled once,
478 * with the most recent delay value that was provided.
479 * </p><p>
480 * Scheduling a job that is waiting or sleeping has no effect.
481 * </p>
482 *
483 * @param delay a time delay in milliseconds before the job should run
484 * @see ISchedulingRule
485 */
486 public final void schedule(long delay) {
487 super.schedule(delay);
488 }
489
490 /**
491 * Changes the name of this job. If the job is currently running, waiting,
492 * or sleeping, the new job name may not take effect until the next time the
493 * job is scheduled.
494 * <p>
495 * The job name is a human-readable value that is displayed to users. The name
496 * does not need to be unique, but it must not be <code>null</code>.
497 *
498 * @param name the name of the job.
499 */
500 public final void setName(String name) {
501 super.setName(name);
502 }
503
504 /**
505 * Sets the priority of the job. This will not affect the execution of
506 * a running job, but it will affect how the job is scheduled while
507 * it is waiting to be run.
508 *
509 * @param priority the new job priority. One of
510 * INTERACTIVE, SHORT, LONG, BUILD, or DECORATE.
511 */
512 public final void setPriority(int priority) {
513 super.setPriority(priority);
514 }
515
516 /**
517 * Associates this job with a progress group. Progress feedback
518 * on this job's next execution will be displayed together with other
519 * jobs in that group. The provided monitor must be a monitor
520 * created by the method <tt>IJobManager.createProgressGroup</tt>
521 * and must have at least <code>ticks</code> units of available work.
522 * <p>
523 * The progress group must be set before the job is scheduled.
524 * The group will be used only for a single invocation of the job's
525 * <tt>run</tt> method, after which any association of this job to the
526 * group will be lost.
527 *
528 * @see IJobManager#createProgressGroup()
529 * @param group The progress group to use for this job
530 * @param ticks the number of work ticks allocated from the
531 * parent monitor, or {@link IProgressMonitor#UNKNOWN}
532 */
533 public final void setProgressGroup(IProgressMonitor group, int ticks) {
534 super.setProgressGroup(group, ticks);
535 }
536
537 /**
538 * Sets the value of the property of this job identified
539 * by the given key. If the supplied value is <code>null</code>,
540 * the property is removed from this resource.
541 * <p>
542 * Properties are intended to be used as a caching mechanism
543 * by ISV plug-ins. They allow key-object associations to be stored with
544 * a job instance. These key-value associations are maintained in
545 * memory (at all times), and the information is never discarded automatically.
546 * </p><p>
547 * The qualifier part of the property name must be the unique identifier
548 * of the declaring plug-in (e.g. <code>"com.example.plugin"</code>).
549 * </p>
550 *
551 * @param key the qualified name of the property
552 * @param value the value of the property,
553 * or <code>null</code> if the property is to be removed
554 * @see #getProperty(QualifiedName)
555 */
556 public void setProperty(QualifiedName key, Object value) {
557 super.setProperty(key, value);
558 }
559
560 /**
561 * Sets the scheduling rule to be used when scheduling this job. This method
562 * must be called before the job is scheduled.
563 *
564 * @param rule the new scheduling rule, or <code>null</code> if the job
565 * should have no scheduling rule
566 * @see #getRule()
567 */
568 public final void setRule(ISchedulingRule rule) {
569 super.setRule(rule);
570 }
571
572 /**
573 * Sets whether or not this job is a system job. System jobs are typically not
574 * revealed to users in any UI presentation of jobs. Other than their UI presentation,
575 * system jobs act exactly like other jobs. If this value is not explicitly set, jobs
576 * are treated as non-system jobs. This method must be called before the job
577 * is scheduled.
578 *
579 * @param value <code>true</code> if this job should be a system job, and
580 * <code>false</code> otherwise.
581 * @see #isSystem()
582 */
583 public final void setSystem(bool value) {
584 super.setSystem(value);
585 }
586
587 /**
588 * Sets whether or not this job has been directly initiated by a UI end user.
589 * These jobs may be presented differently in the UI. This method must be
590 * called before the job is scheduled.
591 *
592 * @param value <code>true</code> if this job is a user-initiated job, and
593 * <code>false</code> otherwise.
594 * @see #isUser()
595 */
596 public final void setUser(bool value) {
597 super.setUser(value);
598 }
599
600 /**
601 * Sets the thread that this job is currently running in, or <code>null</code>
602 * if this job is not running or the thread is unknown.
603 * <p>
604 * Jobs that use the {@link #ASYNC_FINISH} return code should tell
605 * the job what thread it is running in. This is used to prevent deadlocks.
606 *
607 * @param thread the thread that this job is running in.
608 *
609 * @see #ASYNC_FINISH
610 * @see #run(IProgressMonitor)
611 */
612 public final void setThread(Thread thread) {
613 super.setThread(thread);
614 }
615
616 /**
617 * Returns whether this job should be run.
618 * If <code>false</code> is returned, this job will be discarded by the job manager
619 * without running.
620 * <p>
621 * This method is called immediately prior to calling the job's
622 * run method, so it can be used for last minute pre-condition checking before
623 * a job is run. This method must not attempt to schedule or change the
624 * state of any other job.
625 * </p><p>
626 * Clients may override this method. This default implementation always returns
627 * <code>true</code>.
628 * </p>
629 *
630 * @return <code>true</code> if this job should be run
631 * and <code>false</code> otherwise
632 */
633 public bool shouldRun() {
634 return true;
635 }
636
637 /**
638 * Returns whether this job should be scheduled.
639 * If <code>false</code> is returned, this job will be discarded by the job manager
640 * without being added to the queue.
641 * <p>
642 * This method is called immediately prior to adding the job to the waiting job
643 * queue.,so it can be used for last minute pre-condition checking before
644 * a job is scheduled.
645 * </p><p>
646 * Clients may override this method. This default implementation always returns
647 * <code>true</code>.
648 * </p>
649 *
650 * @return <code>true</code> if the job manager should schedule this job
651 * and <code>false</code> otherwise
652 */
653 public bool shouldSchedule() {
654 return true;
655 }
656
657 /**
658 * Requests that this job be suspended. If the job is currently waiting to be run, it
659 * will be removed from the queue move into the {@link #SLEEPING} state.
660 * The job will remain asleep until either resumed or canceled. If this job is not
661 * currently waiting to be run, this method has no effect.
662 * <p>
663 * Sleeping jobs can be resumed using <code>wakeUp</code>.
664 *
665 * @return <code>false</code> if the job is currently running (and thus cannot
666 * be put to sleep), and <code>true</code> in all other cases
667 * @see #wakeUp()
668 */
669 public final bool sleep() {
670 return super.sleep();
671 }
672
673 /**
674 * Puts this job immediately into the {@link #WAITING} state so that it is
675 * eligible for immediate execution. If this job is not currently sleeping,
676 * the request is ignored.
677 * <p>
678 * This is a convenience method, fully equivalent to
679 * <code>wakeUp(0L)</code>.
680 * </p>
681 * @see #sleep()
682 */
683 public final void wakeUp() {
684 super.wakeUp(0L);
685 }
686
687 /**
688 * Puts this job back into the {@link #WAITING} state after
689 * the specified delay. This is equivalent to canceling the sleeping job and
690 * rescheduling with the given delay. If this job is not currently sleeping,
691 * the request is ignored.
692 *
693 * @param delay the number of milliseconds to delay
694 * @see #sleep()
695 */
696 public final void wakeUp(long delay) {
697 super.wakeUp(delay);
698 }
699 }