/** * Returns the job manager singleton. For internal use only. */ static synchronized JobManager getInstance() { if (instance == null) new JobManager(); return instance; }
protected void setProgressGroup(IProgressMonitor group, int ticks) { Assert.isNotNull(group); IProgressMonitor pm = manager.createMonitor(this, group, ticks); if (pm != null) setProgressMonitor(pm); }
public void join(final Object family, IProgressMonitor monitor) throws InterruptedException, OperationCanceledException { monitor = monitorFor(monitor); IJobChangeListener listener = null; final Set jobs; jobs = Collections.synchronizedSet(new HashSet(select(family, states))); jobCount = jobs.size(); if (jobCount > 0) { addJobChangeListener(listener); monitor.subTask(getWaitMessage(jobCount)); reportBlocked(monitor, blocking); int jobsLeft; int reportedWorkDone = 0; monitor.worked(actualWorkDone - reportedWorkDone); reportedWorkDone = actualWorkDone; monitor.subTask(getWaitMessage(jobsLeft)); removeJobChangeListener(listener); reportUnblocked(monitor); monitor.done();
void begin(ISchedulingRule rule, IProgressMonitor monitor, boolean suspend) { if (JobManager.DEBUG_BEGIN_END) JobManager.debug("Begin rule: " + rule); //$NON-NLS-1$ final Thread currentThread = Thread.currentThread(); ThreadJob threadJob; return; Job realJob = manager.currentJob(); if (realJob != null && realJob.getRule() != null) threadJob = newThreadJob(realJob.getRule()); if (manager.runNow(threadJob)) manager.getLockManager().addLockThread(Thread.currentThread(), rule); else threadJob = threadJob.joinRun(monitor); manager.reportUnblocked(monitor);
InternalJob job = sleeping.peek(); while (job != null && job.getStartTime() < now) { job.setStartTime(now + delayFor(job.getPriority())); job.setWaitQueueStamp(waitQueueCounter++); changeState(job, Job.WAITING); job = sleeping.peek(); InternalJob blocker = findBlockingJob(job); if (blocker == null) break; changeState(job, InternalJob.BLOCKED); changeState(job, InternalJob.ABOUT_TO_RUN); if (JobManager.DEBUG) JobManager.debug("Starting job: " + job); //$NON-NLS-1$
Job job = null; while (true) { job = nextJob(); if (job == null) return null; boolean shouldRun = shouldRun(job); if (internal.internalGetState() == InternalJob.ABOUT_TO_RUN) { if (shouldRun && !internal.isAboutToRunCanceled()) { internal.setProgressMonitor(createMonitor(job)); endJob(job, Status.CANCEL_STATUS, true); continue;
protected void schedule(InternalJob job, long delay, boolean reschedule) { if (!active) throw new IllegalStateException("Job manager has been shut down."); //$NON-NLS-1$ Assert.isNotNull(job, "Job is null"); //$NON-NLS-1$ Assert.isLegal(delay >= 0, "Scheduling delay is negative"); //$NON-NLS-1$ synchronized (lock) { //if the job is already running, set it to be rescheduled when done if (job.getState() == Job.RUNNING) { job.setStartTime(delay); return; } //can't schedule a job that is waiting or sleeping if (job.internalGetState() != Job.NONE) return; if (JobManager.DEBUG) JobManager.debug("Scheduling job: " + job); //$NON-NLS-1$ //remember that we are about to schedule the job //to prevent multiple schedule attempts from succeeding (bug 68452) changeState(job, InternalJob.ABOUT_TO_SCHEDULE); } //notify listeners outside sync block jobListeners.scheduled((Job) job, delay, reschedule); //schedule the job doSchedule(job, delay); //call the pool outside sync block to avoid deadlock pool.jobQueued(); }
/** * Indicates that a job was running, and has now finished. Note that this method * can be called under OutOfMemoryError conditions and thus must be paranoid * about allocating objects. */ protected void endJob(InternalJob job, IStatus result, boolean notify) { long rescheduleDelay = InternalJob.T_NONE; synchronized (lock) { //if the job is finishing asynchronously, there is nothing more to do for now if (result == Job.ASYNC_FINISH) return; //if job is not known then it cannot be done if (job.getState() == Job.NONE) return; if (JobManager.DEBUG && notify) JobManager.debug("Ending job: " + job); //$NON-NLS-1$ job.setResult(result); job.setProgressMonitor(null); job.setThread(null); rescheduleDelay = job.getStartTime(); changeState(job, Job.NONE); } //notify listeners outside sync block final boolean reschedule = active && rescheduleDelay > InternalJob.T_NONE && job.shouldSchedule(); if (notify) jobListeners.done((Job) job, result, reschedule); //reschedule the job if requested and we are still active if (reschedule) schedule(job, rescheduleDelay, reschedule); }
cancel(toCancel[i]); // cancel jobs outside sync block to avoid deadlock JobManager.debug("Shutdown - job wait cycle #" + (waitAttempts + 1)); //$NON-NLS-1$ Job[] stillRunning = null; synchronized (lock) { JobManager.debug("\tJob: " + printJobName(stillRunning[j])); //$NON-NLS-1$ if (toCancel != null) { for (int i = 0; i < toCancel.length; i++) { String jobName = printJobName(toCancel[i]);
/** * Sleep for the given duration or until woken. */ private synchronized void sleep(long duration) { sleepingThreads++; busyThreads--; if (JobManager.DEBUG) JobManager.debug("worker sleeping for: " + duration + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ try { wait(duration); } catch (InterruptedException e) { if (JobManager.DEBUG) JobManager.debug("worker interrupted while waiting... :-|"); //$NON-NLS-1$ } finally { sleepingThreads--; busyThreads++; } }
Job job = null; while (true) { job = nextJob(); if (job == null) return null; if (internal.internalGetState() == InternalJob.ABOUT_TO_RUN) { if (shouldRun && !internal.isAboutToRunCanceled()) { internal.setProgressMonitor(createMonitor(job)); endJob(job, Status.CANCEL_STATUS, true); continue;
/** * Attempts to immediately start a given job. Returns true if the job was * successfully started, and false if it could not be started immediately * due to a currently running job with a conflicting rule. Listeners will never * be notified of jobs that are run in this way. */ protected boolean runNow(InternalJob job) { synchronized (lock) { //cannot start if there is a conflicting job if (findBlockingJob(job) != null) return false; changeState(job, Job.RUNNING); job.setProgressMonitor(new NullProgressMonitor()); job.run(null); } return true; }
/** * Performs the scheduling of a job. Does not perform any notifications. */ private void doSchedule(InternalJob job, long delay) { synchronized (lock) { //job may have been canceled already int state = job.internalGetState(); if (state != InternalJob.ABOUT_TO_SCHEDULE && state != Job.SLEEPING) return; //if it's a decoration job with no rule, don't run it right now if the system is busy if (job.getPriority() == Job.DECORATE && job.getRule() == null) { long minDelay = running.size() * 100; delay = Math.max(delay, minDelay); } if (delay > 0) { job.setStartTime(System.currentTimeMillis() + delay); changeState(job, Job.SLEEPING); } else { job.setStartTime(System.currentTimeMillis() + delayFor(job.getPriority())); job.setWaitQueueStamp(waitQueueCounter++); changeState(job, Job.WAITING); } } }
protected void cancel() { manager.cancel(this); }
/** * Returns the job group of the job currently running in this thread. Will return null if * either this thread is not running a job or the job is not part of a job group. */ private JobGroup getGroupOfCurrentlyRunningJob() { Job job = manager.currentJob(); return job == null ? null : job.getJobGroup(); }
/** * Note that although this method is not API, clients have historically used * it to force jobs shutdown in cases where OSGi shutdown does not occur. * For this reason, this method should be considered near-API and should not * be changed if at all possible. */ public static void shutdown() { if (instance != null) { instance.doShutdown(); instance = null; } }
protected void wakeUp(InternalJob job, long delay) { Assert.isLegal(delay >= 0, "Scheduling delay is negative"); //$NON-NLS-1$ synchronized (lock) { //cannot wake up if it is not sleeping if (job.getState() != Job.SLEEPING) return; doSchedule(job, delay); } //call the pool outside sync block to avoid deadlock pool.jobQueued(); //only notify of wake up if immediate if (delay == 0) jobListeners.awake((Job) job); }
/** * Changes a job priority. */ protected void setPriority(InternalJob job, int newPriority) { synchronized (lock) { int oldPriority = job.getPriority(); if (oldPriority == newPriority) return; job.internalSetPriority(newPriority); //if the job is waiting to run, re-shuffle the queue if (job.getState() == Job.WAITING) { long oldStart = job.getStartTime(); job.setStartTime(oldStart + (delayFor(newPriority) - delayFor(oldPriority))); waiting.resort(job); } } }
/** * Puts a job to sleep. Returns true if the job was successfully put to sleep. */ protected boolean sleep(InternalJob job) { synchronized (lock) { switch (job.getState()) { case Job.RUNNING : //cannot be paused if it is already running (as opposed to ABOUT_TO_RUN) if (job.internalGetState() == Job.RUNNING) return false; //job hasn't started running yet (aboutToRun listener) break; case Job.SLEEPING : //update the job wake time job.setStartTime(InternalJob.T_INFINITE); //change state again to re-shuffle the sleep queue changeState(job, Job.SLEEPING); return true; case Job.NONE : return true; case Job.WAITING : //put the job to sleep break; } job.setStartTime(InternalJob.T_INFINITE); changeState(job, Job.SLEEPING); } jobListeners.sleeping((Job) job); return true; }