1 11 package org.eclipse.core.internal.jobs; 12 13 import java.text.*; 15 import java.util.*; 16 import org.eclipse.core.internal.runtime.RuntimeLog; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.core.runtime.jobs.*; 19 import org.eclipse.osgi.util.NLS; 20 21 33 public class JobManager implements IJobManager { 34 35 38 public static final String PI_JOBS = "org.eclipse.core.jobs"; 40 44 public static final int PLUGIN_ERROR = 2; 45 46 private static final String OPTION_DEADLOCK_ERROR = PI_JOBS + "/jobs/errorondeadlock"; private static final String OPTION_DEBUG_BEGIN_END = PI_JOBS + "/jobs/beginend"; private static final String OPTION_DEBUG_JOBS = PI_JOBS + "/jobs"; private static final String OPTION_DEBUG_JOBS_TIMING = PI_JOBS + "/jobs/timing"; private static final String OPTION_LOCKS = PI_JOBS + "/jobs/locks"; private static final String OPTION_SHUTDOWN = PI_JOBS + "/jobs/shutdown"; 53 static boolean DEBUG = false; 54 static boolean DEBUG_BEGIN_END = false; 55 static boolean DEBUG_DEADLOCK = false; 56 static boolean DEBUG_LOCKS = false; 57 static boolean DEBUG_TIMING = false; 58 static boolean DEBUG_SHUTDOWN = false; 59 private static DateFormat DEBUG_FORMAT; 60 61 66 private static JobManager instance; 67 70 private static final ISchedulingRule nullRule = new ISchedulingRule() { 71 public boolean contains(ISchedulingRule rule) { 72 return rule == this; 73 } 74 75 public boolean isConflicting(ISchedulingRule rule) { 76 return rule == this; 77 } 78 }; 79 80 85 private volatile boolean active = true; 86 87 final ImplicitJobs implicitJobs = new ImplicitJobs(this); 88 89 private final JobListeners jobListeners = new JobListeners(); 90 91 96 private final Object lock = new Object (); 97 98 private final LockManager lockManager = new LockManager(); 99 100 103 private WorkerPool pool; 104 105 private ProgressProvider progressProvider = null; 106 109 private final HashSet running; 110 111 116 private final JobQueue sleeping; 117 123 private boolean suspended = false; 124 125 128 private final JobQueue waiting; 129 130 public static void debug(String msg) { 131 StringBuffer msgBuf = new StringBuffer (msg.length() + 40); 132 if (DEBUG_TIMING) { 133 if (DEBUG_FORMAT == null) 135 DEBUG_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS"); DEBUG_FORMAT.format(new Date(), msgBuf, new FieldPosition(0)); 137 msgBuf.append('-'); 138 } 139 msgBuf.append('[').append(Thread.currentThread()).append(']').append(msg); 140 System.out.println(msgBuf.toString()); 141 } 142 143 146 static synchronized JobManager getInstance() { 147 if (instance == null) 148 new JobManager(); 149 return instance; 150 } 151 152 155 private static String printJobName(Job job) { 156 if (job instanceof ThreadJob) { 157 Job realJob = ((ThreadJob) job).realJob; 158 if (realJob != null) 159 return realJob.getClass().getName(); 160 return "ThreadJob on rule: " + job.getRule(); } 162 return job.getClass().getName(); 163 } 164 165 168 public static String printState(int state) { 169 switch (state) { 170 case Job.NONE : 171 return "NONE"; case Job.WAITING : 173 return "WAITING"; case Job.SLEEPING : 175 return "SLEEPING"; case Job.RUNNING : 177 return "RUNNING"; case InternalJob.BLOCKED : 179 return "BLOCKED"; case InternalJob.ABOUT_TO_RUN : 181 return "ABOUT_TO_RUN"; case InternalJob.ABOUT_TO_SCHEDULE : 183 return "ABOUT_TO_SCHEDULE"; } 185 return "UNKNOWN"; } 187 188 194 public static void shutdown() { 195 if (instance != null) { 196 instance.doShutdown(); 197 instance = null; 198 } 199 } 200 201 private JobManager() { 202 instance = this; 203 initDebugOptions(); 204 synchronized (lock) { 205 waiting = new JobQueue(false); 206 sleeping = new JobQueue(true); 207 running = new HashSet(10); 208 pool = new WorkerPool(this); 209 } 210 pool.setDaemon(JobOSGiUtils.getDefault().useDaemonThreads()); 211 } 212 213 216 public void addJobChangeListener(IJobChangeListener listener) { 217 jobListeners.add(listener); 218 } 219 220 223 public void beginRule(ISchedulingRule rule, IProgressMonitor monitor) { 224 validateRule(rule); 225 implicitJobs.begin(rule, monitorFor(monitor), false); 226 } 227 228 231 protected boolean cancel(InternalJob job) { 232 IProgressMonitor monitor = null; 233 synchronized (lock) { 234 switch (job.getState()) { 235 case Job.NONE : 236 return true; 237 case Job.RUNNING : 238 if (job.internalGetState() == Job.RUNNING) { 240 monitor = job.getProgressMonitor(); 241 break; 242 } 243 job.setAboutToRunCanceled(true); 245 return true; 246 default : 247 changeState(job, Job.NONE); 248 } 249 } 250 if (monitor != null) { 252 if (!monitor.isCanceled()) { 253 monitor.setCanceled(true); 254 job.canceling(); 255 } 256 return false; 257 } 258 jobListeners.done((Job) job, Status.CANCEL_STATUS, false); 260 return true; 261 } 262 263 266 public void cancel(Object family) { 267 for (Iterator it = select(family).iterator(); it.hasNext();) 269 cancel((Job) it.next()); 270 } 271 272 276 private void changeState(InternalJob job, int newState) { 277 boolean blockedJobs = false; 278 synchronized (lock) { 279 int oldState = job.internalGetState(); 280 switch (oldState) { 281 case Job.NONE : 282 case InternalJob.ABOUT_TO_SCHEDULE : 283 break; 284 case InternalJob.BLOCKED : 285 job.remove(); 287 break; 288 case Job.WAITING : 289 try { 290 waiting.remove(job); 291 } catch (RuntimeException e) { 292 Assert.isLegal(false, "Tried to remove a job that wasn't in the queue"); } 294 break; 295 case Job.SLEEPING : 296 try { 297 sleeping.remove(job); 298 } catch (RuntimeException e) { 299 Assert.isLegal(false, "Tried to remove a job that wasn't in the queue"); } 301 break; 302 case Job.RUNNING : 303 case InternalJob.ABOUT_TO_RUN : 304 running.remove(job); 305 InternalJob blocked = job.previous(); 307 job.remove(); 308 blockedJobs = blocked != null; 309 while (blocked != null) { 310 InternalJob previous = blocked.previous(); 311 changeState(blocked, Job.WAITING); 312 blocked = previous; 313 } 314 break; 315 default : 316 Assert.isLegal(false, "Invalid job state: " + job + ", state: " + oldState); } 318 job.internalSetState(newState); 319 switch (newState) { 320 case Job.NONE : 321 job.setStartTime(InternalJob.T_NONE); 322 case InternalJob.BLOCKED : 323 break; 324 case Job.WAITING : 325 waiting.enqueue(job); 326 break; 327 case Job.SLEEPING : 328 try { 329 sleeping.enqueue(job); 330 } catch (RuntimeException e) { 331 throw new RuntimeException ("Error changing from state: " + oldState); } 333 break; 334 case Job.RUNNING : 335 case InternalJob.ABOUT_TO_RUN : 336 job.setStartTime(InternalJob.T_NONE); 337 running.add(job); 338 break; 339 case InternalJob.ABOUT_TO_SCHEDULE : 340 break; 341 default : 342 Assert.isLegal(false, "Invalid job state: " + job + ", state: " + newState); } 344 } 345 if (blockedJobs) 347 pool.jobQueued(); 348 } 349 350 354 protected IProgressMonitor createMonitor(InternalJob job, IProgressMonitor group, int ticks) { 355 synchronized (lock) { 356 if (job.getState() != Job.NONE) 360 return null; 361 IProgressMonitor monitor = null; 362 if (progressProvider != null) 363 monitor = progressProvider.createMonitor((Job) job, group, ticks); 364 if (monitor == null) 365 monitor = new NullProgressMonitor(); 366 return monitor; 367 } 368 } 369 370 373 private IProgressMonitor createMonitor(Job job) { 374 IProgressMonitor monitor = null; 375 if (progressProvider != null) 376 monitor = progressProvider.createMonitor(job); 377 if (monitor == null) 378 monitor = new NullProgressMonitor(); 379 return monitor; 380 } 381 382 385 public IProgressMonitor createProgressGroup() { 386 if (progressProvider != null) 387 return progressProvider.createProgressGroup(); 388 return new NullProgressMonitor(); 389 } 390 391 394 public Job currentJob() { 395 Thread current = Thread.currentThread(); 396 if (current instanceof Worker) 397 return ((Worker) current).currentJob(); 398 synchronized (lock) { 399 for (Iterator it = running.iterator(); it.hasNext();) { 400 Job job = (Job) it.next(); 401 if (job.getThread() == current) 402 return job; 403 } 404 } 405 return null; 406 } 407 408 412 private long delayFor(int priority) { 413 switch (priority) { 415 case Job.INTERACTIVE : 416 return 0L; 417 case Job.SHORT : 418 return 50L; 419 case Job.LONG : 420 return 100L; 421 case Job.BUILD : 422 return 500L; 423 case Job.DECORATE : 424 return 1000L; 425 default : 426 Assert.isTrue(false, "Job has invalid priority: " + priority); return 0; 428 } 429 } 430 431 434 private void doSchedule(InternalJob job, long delay) { 435 synchronized (lock) { 436 if (job.getPriority() == Job.DECORATE) { 438 long minDelay = running.size() * 100; 439 delay = Math.max(delay, minDelay); 440 } 441 if (delay > 0) { 442 job.setStartTime(System.currentTimeMillis() + delay); 443 changeState(job, Job.SLEEPING); 444 } else { 445 job.setStartTime(System.currentTimeMillis() + delayFor(job.getPriority())); 446 changeState(job, Job.WAITING); 447 } 448 } 449 } 450 451 457 private void doShutdown() { 458 Job[] toCancel = null; 459 synchronized (lock) { 460 if (active) { 461 active = false; 462 toCancel = (Job[]) running.toArray(new Job[running.size()]); 464 sleeping.clear(); 466 waiting.clear(); 467 running.clear(); 468 } 469 } 470 471 if (toCancel != null && toCancel.length > 0) { 473 for (int i = 0; i < toCancel.length; i++) { 474 cancel(toCancel[i]); } 476 477 for (int waitAttempts = 0; waitAttempts < 3; waitAttempts++) { 478 Thread.yield(); 479 synchronized (lock) { 480 if (running.isEmpty()) 481 break; 482 } 483 if (DEBUG_SHUTDOWN) { 484 JobManager.debug("Shutdown - job wait cycle #" + (waitAttempts + 1)); Job[] stillRunning = null; 486 synchronized (lock) { 487 stillRunning = (Job[]) running.toArray(new Job[running.size()]); 488 } 489 if (stillRunning != null) { 490 for (int j = 0; j < stillRunning.length; j++) { 491 JobManager.debug("\tJob: " + printJobName(stillRunning[j])); } 493 } 494 } 495 try { 496 Thread.sleep(100); 497 } catch (InterruptedException e) { 498 } 500 Thread.yield(); 501 } 502 503 synchronized (lock) { toCancel = (Job[]) running.toArray(new Job[running.size()]); 505 } 506 } 507 508 if (toCancel != null) { 509 for (int i = 0; i < toCancel.length; i++) { 510 String jobName = printJobName(toCancel[i]); 511 String msg = "Job found still running after platform shutdown. Jobs should be canceled by the plugin that scheduled them during shutdown: " + jobName; RuntimeLog.log(new Status(IStatus.WARNING, JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, null)); 514 515 System.err.println(msg); 519 } 520 } 521 522 pool.shutdown(); 523 } 524 525 530 protected void endJob(InternalJob job, IStatus result, boolean notify) { 531 long rescheduleDelay = InternalJob.T_NONE; 532 synchronized (lock) { 533 if (result == Job.ASYNC_FINISH) 535 return; 536 if (job.getState() == Job.NONE) 538 return; 539 if (JobManager.DEBUG && notify) 540 JobManager.debug("Ending job: " + job); job.setResult(result); 542 job.setProgressMonitor(null); 543 job.setThread(null); 544 rescheduleDelay = job.getStartTime(); 545 changeState(job, Job.NONE); 546 } 547 final boolean reschedule = active && rescheduleDelay > InternalJob.T_NONE && job.shouldSchedule(); 549 if (notify) 550 jobListeners.done((Job) job, result, reschedule); 551 if (reschedule) 553 schedule(job, rescheduleDelay, reschedule); 554 } 555 556 559 public void endRule(ISchedulingRule rule) { 560 implicitJobs.end(rule, false); 561 } 562 563 566 public Job[] find(Object family) { 567 List members = select(family); 568 return (Job[]) members.toArray(new Job[members.size()]); 569 } 570 571 577 protected InternalJob findBlockingJob(InternalJob waitingJob) { 578 if (waitingJob.getRule() == null) 579 return null; 580 synchronized (lock) { 581 if (running.isEmpty()) 582 return null; 583 boolean hasBlockedJobs = false; 585 for (Iterator it = running.iterator(); it.hasNext();) { 586 InternalJob job = (InternalJob) it.next(); 587 if (waitingJob.isConflicting(job)) 588 return job; 589 if (!hasBlockedJobs) 590 hasBlockedJobs = job.previous() != null; 591 } 592 if (!hasBlockedJobs) 594 return null; 595 for (Iterator it = running.iterator(); it.hasNext();) { 597 InternalJob job = (InternalJob) it.next(); 598 while (true) { 599 job = job.previous(); 600 if (job == null) 601 break; 602 if (waitingJob.isConflicting(job)) 603 return job; 604 } 605 } 606 } 607 return null; 608 } 609 610 public LockManager getLockManager() { 611 return lockManager; 612 } 613 614 private void initDebugOptions() { 615 DEBUG = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_DEBUG_JOBS, false); 616 DEBUG_BEGIN_END = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_DEBUG_BEGIN_END, false); 617 DEBUG_DEADLOCK = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_DEADLOCK_ERROR, false); 618 DEBUG_LOCKS = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_LOCKS, false); 619 DEBUG_TIMING = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_DEBUG_JOBS_TIMING, false); 620 DEBUG_SHUTDOWN = JobOSGiUtils.getDefault().getBooleanDebugOption(OPTION_SHUTDOWN, false); 621 } 622 623 626 protected boolean isActive() { 627 return active; 628 } 629 630 634 protected boolean isBlocking(InternalJob runningJob) { 635 synchronized (lock) { 636 if (runningJob.getState() != Job.RUNNING) 638 return false; 639 InternalJob previous = runningJob.previous(); 641 while (previous != null) { 642 if (previous.getPriority() < runningJob.getPriority()) { 644 if (!previous.isSystem()) 645 return true; 646 if (previous instanceof ThreadJob && ((ThreadJob) previous).shouldInterrupt()) 648 return true; 649 } 650 previous = previous.previous(); 651 } 652 return false; 654 } 655 } 656 657 660 public boolean isIdle() { 661 synchronized (lock) { 662 return running.isEmpty() && waiting.isEmpty(); 663 } 664 } 665 666 669 protected void join(InternalJob job) { 670 final IJobChangeListener listener; 671 final Semaphore barrier; 672 synchronized (lock) { 673 int state = job.getState(); 674 if (state == Job.NONE) 675 return; 676 if (suspended && state != Job.RUNNING) 678 return; 679 if (state == Job.RUNNING && job.getThread() == Thread.currentThread()) 681 throw new IllegalStateException ("Job attempted to join itself"); barrier = new Semaphore(null); 684 listener = new JobChangeAdapter() { 685 public void done(IJobChangeEvent event) { 686 barrier.release(); 687 } 688 }; 689 job.addJobChangeListener(listener); 690 } 693 try { 695 while (true) { 696 lockManager.aboutToWait(job.getThread()); 698 try { 699 if (barrier.acquire(Long.MAX_VALUE)) 700 break; 701 } catch (InterruptedException e) { 702 } 704 } 705 } finally { 706 lockManager.aboutToRelease(); 707 job.removeJobChangeListener(listener); 708 } 709 } 710 711 714 public void join(final Object family, IProgressMonitor monitor) throws InterruptedException , OperationCanceledException { 715 monitor = monitorFor(monitor); 716 IJobChangeListener listener = null; 717 final Set jobs; 718 int jobCount; 719 Job blocking = null; 720 synchronized (lock) { 721 int states = suspended ? Job.RUNNING : Job.RUNNING | Job.WAITING | Job.SLEEPING; 723 jobs = Collections.synchronizedSet(new HashSet(select(family, states))); 724 jobCount = jobs.size(); 725 if (jobCount > 0) { 726 if (jobCount == 1) 728 blocking = (Job) jobs.iterator().next(); 729 listener = new JobChangeAdapter() { 730 public void done(IJobChangeEvent event) { 731 if (!((JobChangeEvent) event).reschedule) 733 jobs.remove(event.getJob()); 734 } 735 736 public void scheduled(IJobChangeEvent event) { 738 if (((JobChangeEvent) event).reschedule) 740 return; 741 Job job = event.getJob(); 742 if (job.belongsTo(family)) 743 jobs.add(job); 744 } 745 }; 746 addJobChangeListener(listener); 747 } 748 } 749 if (jobCount == 0) { 750 monitor.beginTask(JobMessages.jobs_blocked0, 1); 752 monitor.done(); 753 return; 754 } 755 try { 757 monitor.beginTask(JobMessages.jobs_blocked0, jobCount); 758 monitor.subTask(NLS.bind(JobMessages.jobs_waitFamSub, Integer.toString(jobCount))); 759 reportBlocked(monitor, blocking); 760 int jobsLeft; 761 int reportedWorkDone = 0; 762 while ((jobsLeft = jobs.size()) > 0) { 763 int actualWorkDone = Math.max(0, jobCount - jobsLeft); 766 if (reportedWorkDone < actualWorkDone) { 767 monitor.worked(actualWorkDone - reportedWorkDone); 768 reportedWorkDone = actualWorkDone; 769 monitor.subTask(NLS.bind(JobMessages.jobs_waitFamSub, Integer.toString(jobsLeft))); 770 } 771 if (Thread.interrupted()) 772 throw new InterruptedException (); 773 if (monitor.isCanceled()) 774 throw new OperationCanceledException(); 775 lockManager.aboutToWait(null); 777 Thread.sleep(100); 778 } 779 } finally { 780 lockManager.aboutToRelease(); 781 removeJobChangeListener(listener); 782 reportUnblocked(monitor); 783 monitor.done(); 784 } 785 } 786 787 792 private IProgressMonitor monitorFor(IProgressMonitor monitor) { 793 if (monitor == null || (monitor instanceof NullProgressMonitor)) { 794 if (progressProvider != null) { 795 try { 796 monitor = progressProvider.getDefaultMonitor(); 797 } catch (Exception e) { 798 String msg = NLS.bind(JobMessages.meta_pluginProblems, JobManager.PI_JOBS); 799 RuntimeLog.log(new Status(IStatus.ERROR, JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, e)); 800 } 801 } 802 } 803 804 if (monitor == null) 805 return new NullProgressMonitor(); 806 return monitor; 807 } 808 809 812 public ILock newLock() { 813 return lockManager.newLock(); 814 } 815 816 821 private Job nextJob() { 822 synchronized (lock) { 823 if (suspended) 825 return null; 826 long now = System.currentTimeMillis(); 828 InternalJob job = sleeping.peek(); 829 while (job != null && job.getStartTime() < now) { 830 job.setStartTime(now + delayFor(job.getPriority())); 831 changeState(job, Job.WAITING); 832 job = sleeping.peek(); 833 } 834 while ((job = waiting.peek()) != null) { 836 InternalJob blocker = findBlockingJob(job); 837 if (blocker == null) 838 break; 839 changeState(job, InternalJob.BLOCKED); 841 Assert.isTrue(job.next() == null); 843 Assert.isTrue(job.previous() == null); 844 blocker.addLast(job); 845 } 846 if (job != null) { 849 changeState(job, InternalJob.ABOUT_TO_RUN); 850 if (JobManager.DEBUG) 851 JobManager.debug("Starting job: " + job); } 853 return (Job) job; 854 } 855 } 856 857 860 public void removeJobChangeListener(IJobChangeListener listener) { 861 jobListeners.remove(listener); 862 } 863 864 873 final void reportBlocked(IProgressMonitor monitor, InternalJob blockingJob) { 874 if (!(monitor instanceof IProgressMonitorWithBlocking)) 875 return; 876 IStatus reason; 877 if (blockingJob == null || blockingJob instanceof ThreadJob || blockingJob.isSystem()) { 878 reason = new Status(IStatus.INFO, JobManager.PI_JOBS, 1, JobMessages.jobs_blocked0, null); 879 } else { 880 String msg = NLS.bind(JobMessages.jobs_blocked1, blockingJob.getName()); 881 reason = new JobStatus(IStatus.INFO, (Job) blockingJob, msg); 882 } 883 ((IProgressMonitorWithBlocking) monitor).setBlocked(reason); 884 } 885 886 892 final void reportUnblocked(IProgressMonitor monitor) { 893 if (monitor instanceof IProgressMonitorWithBlocking) 894 ((IProgressMonitorWithBlocking) monitor).clearBlocked(); 895 } 896 897 900 public final void resume() { 901 synchronized (lock) { 902 suspended = false; 903 pool.jobQueued(); 905 } 906 } 907 908 912 public final void resume(ISchedulingRule rule) { 913 implicitJobs.resume(rule); 914 } 915 916 922 protected boolean runNow(InternalJob job) { 923 synchronized (lock) { 924 if (findBlockingJob(job) != null) 926 return false; 927 changeState(job, Job.RUNNING); 928 job.setProgressMonitor(new NullProgressMonitor()); 929 job.run(null); 930 } 931 return true; 932 } 933 934 937 protected void schedule(InternalJob job, long delay, boolean reschedule) { 938 if (!active) 939 throw new IllegalStateException ("Job manager has been shut down."); Assert.isNotNull(job, "Job is null"); Assert.isLegal(delay >= 0, "Scheduling delay is negative"); synchronized (lock) { 943 if (job.getState() == Job.RUNNING) { 945 job.setStartTime(delay); 946 return; 947 } 948 if (job.internalGetState() != Job.NONE) 950 return; 951 if (JobManager.DEBUG) 952 JobManager.debug("Scheduling job: " + job); changeState(job, InternalJob.ABOUT_TO_SCHEDULE); 956 } 957 jobListeners.scheduled((Job) job, delay, reschedule); 959 doSchedule(job, delay); 961 pool.jobQueued(); 963 } 964 965 968 private void select(List members, Object family, InternalJob firstJob, int stateMask) { 969 if (firstJob == null) 970 return; 971 InternalJob job = firstJob; 972 do { 973 if ((family == null || job.belongsTo(family)) && ((job.getState() & stateMask) != 0)) 975 members.add(job); 976 job = job.previous(); 977 } while (job != null && job != firstJob); 978 } 979 980 983 private List select(Object family) { 984 return select(family, Job.WAITING | Job.SLEEPING | Job.RUNNING); 985 } 986 987 991 private List select(Object family, int stateMask) { 992 List members = new ArrayList(); 993 synchronized (lock) { 994 if ((stateMask & Job.RUNNING) != 0) { 995 for (Iterator it = running.iterator(); it.hasNext();) { 996 select(members, family, (InternalJob) it.next(), stateMask); 997 } 998 } 999 if ((stateMask & Job.WAITING) != 0) 1000 select(members, family, waiting.peek(), stateMask); 1001 if ((stateMask & Job.SLEEPING) != 0) 1002 select(members, family, sleeping.peek(), stateMask); 1003 } 1004 return members; 1005 } 1006 1007 1010 public void setLockListener(LockListener listener) { 1011 lockManager.setLockListener(listener); 1012 } 1013 1014 1017 protected void setPriority(InternalJob job, int newPriority) { 1018 synchronized (lock) { 1019 int oldPriority = job.getPriority(); 1020 if (oldPriority == newPriority) 1021 return; 1022 job.internalSetPriority(newPriority); 1023 if (job.getState() == Job.WAITING) { 1025 long oldStart = job.getStartTime(); 1026 job.setStartTime(oldStart + (delayFor(newPriority) - delayFor(oldPriority))); 1027 waiting.resort(job); 1028 } 1029 } 1030 } 1031 1032 1035 public void setProgressProvider(ProgressProvider provider) { 1036 progressProvider = provider; 1037 } 1038 1039 1042 public void setRule(InternalJob job, ISchedulingRule rule) { 1043 synchronized (lock) { 1044 Assert.isLegal(job.getState() == Job.NONE); 1046 validateRule(rule); 1047 job.internalSetRule(rule); 1048 } 1049 } 1050 1051 1054 protected boolean sleep(InternalJob job) { 1055 synchronized (lock) { 1056 switch (job.getState()) { 1057 case Job.RUNNING : 1058 if (job.internalGetState() == Job.RUNNING) 1060 return false; 1061 break; 1063 case Job.SLEEPING : 1064 job.setStartTime(InternalJob.T_INFINITE); 1066 changeState(job, Job.SLEEPING); 1068 return true; 1069 case Job.NONE : 1070 return true; 1071 case Job.WAITING : 1072 break; 1074 } 1075 job.setStartTime(InternalJob.T_INFINITE); 1076 changeState(job, Job.SLEEPING); 1077 } 1078 jobListeners.sleeping((Job) job); 1079 return true; 1080 } 1081 1082 1085 public void sleep(Object family) { 1086 for (Iterator it = select(family).iterator(); it.hasNext();) { 1088 sleep((InternalJob) it.next()); 1089 } 1090 } 1091 1092 1097 protected long sleepHint() { 1098 synchronized (lock) { 1099 if (suspended) 1101 return InternalJob.T_INFINITE; 1102 if (!waiting.isEmpty()) 1103 return 0L; 1104 InternalJob next = sleeping.peek(); 1106 if (next == null) 1107 return InternalJob.T_INFINITE; 1108 return next.getStartTime() - System.currentTimeMillis(); 1109 } 1110 } 1111 1112 1116 protected Job startJob() { 1117 Job job = null; 1118 while (true) { 1119 job = nextJob(); 1120 if (job == null) 1121 return null; 1122 if (job.shouldRun()) { 1124 jobListeners.aboutToRun(job); 1126 synchronized (lock) { 1128 if (job.getState() == Job.RUNNING) { 1129 InternalJob internal = job; 1130 if (internal.isAboutToRunCanceled()) { 1131 internal.setAboutToRunCanceled(false); 1132 } else { 1134 internal.setProgressMonitor(createMonitor(job)); 1135 internal.internalSetState(Job.RUNNING); 1137 break; 1138 } 1139 } 1140 } 1141 } 1142 if (job.getState() != Job.SLEEPING) { 1143 endJob(job, Status.CANCEL_STATUS, true); 1145 continue; 1146 } 1147 } 1148 jobListeners.running(job); 1149 return job; 1150 1151 } 1152 1153 1156 public final void suspend() { 1157 synchronized (lock) { 1158 suspended = true; 1159 } 1160 } 1161 1162 1166 public final void suspend(ISchedulingRule rule, IProgressMonitor monitor) { 1167 Assert.isNotNull(rule); 1168 implicitJobs.suspend(rule, monitorFor(monitor)); 1169 } 1170 1171 1174 public void transferRule(ISchedulingRule rule, Thread destinationThread) { 1175 implicitJobs.transfer(rule, destinationThread); 1176 } 1177 1178 1183 private void validateRule(ISchedulingRule rule) { 1184 if (rule == null) 1186 return; 1187 Assert.isLegal(rule.contains(rule)); 1189 Assert.isLegal(!rule.contains(nullRule)); 1191 Assert.isLegal(rule.isConflicting(rule)); 1193 Assert.isLegal(!rule.isConflicting(nullRule)); 1195 } 1196 1197 1200 protected void wakeUp(InternalJob job, long delay) { 1201 Assert.isLegal(delay >= 0, "Scheduling delay is negative"); synchronized (lock) { 1203 if (job.getState() != Job.SLEEPING) 1205 return; 1206 doSchedule(job, delay); 1207 } 1208 pool.jobQueued(); 1210 1211 if (delay == 0) 1213 jobListeners.awake((Job) job); 1214 } 1215 1216 1219 public void wakeUp(Object family) { 1220 for (Iterator it = select(family).iterator(); it.hasNext();) { 1222 wakeUp((InternalJob) it.next(), 0L); 1223 } 1224 } 1225} 1226 | Popular Tags |