package net.sf.eclipsefp.haskell.util; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; /** * ensure that only one job of a given type runs and only one job waits, intermediate jobs are discarded * @author JP Moresmau * */ public class SingleJobQueue { /** * the currently running job */ private Job current; /** * the next job to run */ private Job next; /** * add a job to the queue * if the queue is empty, schedule the job straight away * otherwise queue the job (losing the previously waiting job if any) * @param j */ public synchronized void addJob(Job j) { if (current==null){ current=j; launchCurrent(); } else { next=j; } } /** * close the queue: cancel current job and remove next */ public synchronized void close(){ next=null; if (current!=null){ current.cancel(); } current=null; } public synchronized boolean hasPendingJob() { return next != null; } /** * launch the current job with a listener that will launch the waiting job on completion */ private void launchCurrent(){ if (current!=null){ current.addJobChangeListener(new ScheduleNextListener()); current.schedule(); } } private class ScheduleNextListener extends JobChangeAdapter { @Override public void done(IJobChangeEvent event) { synchronized (SingleJobQueue.this) { // we're not running current=null; // we have a job waiting, let's run it if (next!=null){ current=next; next=null; launchCurrent(); } } } } }