Package org.rssowl.core.tests

Source Code of org.rssowl.core.tests.TestJobQueue

/*   **********************************************************************  **
**   Copyright notice                                                       **
**                                                                          **
**   (c) 2005-2006 RSSOwl Development Team                                  **
**   http://www.rssowl.org/                                                 **
**                                                                          **
**   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.rssowl.org/legal/epl-v10.html                               **
**                                                                          **
**   A copy is found in the file epl-v10.html and important notices to the  **
**   license from the team is found in the textfile LICENSE.txt distributed **
**   in this package.                                                       **
**                                                                          **
**   This copyright notice MUST APPEAR in all copies of the file!           **
**                                                                          **
**   Contributors:                                                          **
**     RSSOwl Development Team - initial API and implementation             **
**                                                                          **
**  **********************************************************************  */

package org.rssowl.core.tests;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.rssowl.core.internal.Activator;
import org.rssowl.core.util.ITask;
import org.rssowl.core.util.LoggingSafeRunnable;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
* @author bpasero
*/
public class TestJobQueue {
  private final int fMaxConcurrentJobs;

  private final AtomicInteger fScheduledJobs = new AtomicInteger(0);
  private final AtomicInteger fTotalWork = new AtomicInteger(0);
  private final AtomicLong fDuration = new AtomicLong(0);
  private final AtomicInteger fDone = new AtomicInteger(0);

  private final ConcurrentLinkedQueue<ITask> fOpenTasksQueue;

  /**
   * Creates an instance of <code>JobQueue</code> that allows to add
   * <code>Runnables</code> into a Queue to process them in Jobs up to a
   * certain amount of allowed parallel Jobs.
   *
   * @param maxConcurrentJobs The maximum number of concurrent running Tasks.
   */
  public TestJobQueue(int maxConcurrentJobs) {
    fMaxConcurrentJobs = maxConcurrentJobs;
    fOpenTasksQueue = new ConcurrentLinkedQueue<ITask>();
  }

  /**
   * Adds the given List of Tasks into the Queue. Each Runnable is processed in
   * a <code>Job</code> once the number of parallel processed Tasks is below
   * <code>MAX_SCHEDULED_JOBS</code>.
   *
   * @param tasks The Tasks to add into this Queue.
   */
  public void schedule(List<ITask> tasks) {
    final int tasksSize = tasks.size();
    final long start = System.currentTimeMillis();

    /* Ignore empty lists */
    if (tasksSize == 0)
      return;

    /* Add into List of open tasks */
    fOpenTasksQueue.addAll(tasks);

    /* Adjust Total Work Counter */
    fTotalWork.addAndGet(tasksSize);

    /* Optimisation: We are able to release the calling thread without locking. */
    if (fScheduledJobs.get() >= fMaxConcurrentJobs)
      return;

    /* Start a new Job for each free Slot */
    for (int i = 0; i < tasksSize && !fOpenTasksQueue.isEmpty(); ++i) {

      /* Never exceed max number of allowed concurrent Jobs */
      if (fScheduledJobs.incrementAndGet() > fMaxConcurrentJobs) {
        fScheduledJobs.decrementAndGet();
        break;
      }

      /* Create the Job */
      Job job = createJob();

      /* Listen to Job's Lifecycle */
      job.addJobChangeListener(new JobChangeAdapter() {

        /* Update Fields when a Job is Done */
        @Override
        public void done(IJobChangeEvent event) {
          fDone.incrementAndGet();

          if (fDone.get() == fTotalWork.get())
            fDuration.set(System.currentTimeMillis() - start);

          /* Re-Schedule this Job if there is work left to do */
          if (!fOpenTasksQueue.isEmpty())
            event.getJob().schedule();
          else
            fScheduledJobs.decrementAndGet();
        }
      });

      /*
       * Workaround: Since we are using our own Job for displaying Progress, we
       * don't want these Jobs show up in the Progress View. There is currently
       * no bug-free solution of aggregating the Progress of N Jobs into a
       * single Monitor.
       */
      job.setSystem(true);

      /* Schedule it immediately */
      job.schedule();
    }
  }

  /* Create a Job for a Task to handle */
  private Job createJob() {
    Job job = new Job("") { //$NON-NLS-1$
      @Override
      protected IStatus run(final IProgressMonitor monitor) {

        /* Poll the next Task */
        final ITask task = fOpenTasksQueue.poll();

        /* Queue is empty - so all work is done */
        if (task == null)
          return Status.OK_STATUS;

        /* Perform the Operation if not yet Cancelled */
        if (!monitor.isCanceled()) {
          SafeRunner.run(new LoggingSafeRunnable() {
            public void run() throws Exception {
              IStatus status = task.run(monitor);

              /* Log anything that is an Error or Warning */
              if (status.getSeverity() == IStatus.ERROR || status.getSeverity() == IStatus.WARNING)
                Activator.getDefault().getLog().log(status);
            }
          });
        }

        /* Inform about cancelation if present */
        return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
      }

      @Override
      public boolean belongsTo(Object family) {
        return family == TestJobQueue.this;
      }
    };

    return job;
  }

  /**
   * @return The value of done Jobs.
   */
  public int getDone() {
    return fDone.get();
  }

  /**
   * @return The Duration of this Queue.
   */
  public long getDuration() {
    return fDuration.get();
  }
}
TOP

Related Classes of org.rssowl.core.tests.TestJobQueue

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.