| /***************************************************************************** |
| * Copyright (c) 2014 CEA LIST. |
| * |
| * 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.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation |
| *****************************************************************************/ |
| package org.eclipse.papyrus.interoperability.rsa.internal.schedule; |
| |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.papyrus.interoperability.rsa.Activator; |
| |
| /** |
| * Executes a number of parallel tasks on the specified (maximum) amount of threads |
| * |
| * @author Camille Letavernier |
| * |
| */ |
| public class Scheduler { |
| |
| protected int maxThreads; |
| |
| public Scheduler(int maxThreads) { |
| this.maxThreads = Math.max(1, maxThreads); |
| } |
| |
| public void schedule(IProgressMonitor monitor, List<? extends Schedulable> tasks) { |
| |
| List<Schedulable> remainingTasks = new LinkedList<Schedulable>(tasks); |
| List<Schedulable> runningTasks = new LinkedList<Schedulable>(); |
| |
| while (!remainingTasks.isEmpty()) { |
| if (monitor.isCanceled()) { |
| monitor.subTask("Canceling remaining jobs..."); |
| for (Schedulable task : runningTasks) { |
| task.cancel(); |
| } |
| remainingTasks.clear(); // Don't start these transformations at all |
| // Keep waiting: the cancel operation is asynchronous, we still need to wait for the jobs to complete |
| } |
| |
| // Schedule transformations if we have enough threads and they have not all been scheduled |
| while (runningTasks.size() < maxThreads && !remainingTasks.isEmpty()) { |
| final Schedulable task = remainingTasks.remove(0); // Get and remove |
| task.start(); |
| runningTasks.add(task); |
| } |
| |
| if (!runningTasks.isEmpty()) { |
| String waitFor = runningTasks.get(0).getName(); |
| monitor.subTask("Waiting for Import " + waitFor + " to complete..."); |
| } |
| |
| // We can continue if at least one transformation is complete (Leaving a free Thread) |
| boolean canContinue = false; |
| |
| Iterator<Schedulable> iterator = runningTasks.iterator(); |
| while (iterator.hasNext()) { |
| Schedulable runningTask = iterator.next(); |
| if (runningTask.isComplete()) { |
| canContinue = true; |
| iterator.remove(); |
| monitor.worked(1); |
| } |
| } |
| |
| if (!canContinue) { |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException ex) { |
| Activator.log.error(ex); |
| } |
| } |
| } |
| |
| // All transformations have been scheduled (But not necessarily completed): wait for all of them to complete |
| wait(runningTasks, monitor); |
| } |
| |
| |
| // Wait for all (remaining) import transformations to complete |
| protected void wait(List<Schedulable> tasks, IProgressMonitor monitor) { |
| |
| // Transformations still running |
| List<Schedulable> runningTasks = new LinkedList<Schedulable>(tasks); |
| |
| while (!runningTasks.isEmpty()) { |
| if (monitor.isCanceled()) { |
| monitor.subTask("Canceling remaining jobs..."); |
| for (Schedulable task : runningTasks) { |
| task.cancel(); |
| } |
| // Keep waiting: the cancel operation is asynchronous, we still need to wait for the jobs to complete |
| } |
| |
| Iterator<Schedulable> iterator = runningTasks.iterator(); |
| while (iterator.hasNext()) { |
| Schedulable task = iterator.next(); |
| if (task.isComplete()) { |
| iterator.remove(); |
| monitor.worked(1); |
| } |
| } |
| |
| if (!runningTasks.isEmpty()) { |
| String waitFor = runningTasks.get(0).getName(); |
| monitor.subTask("Waiting for " + waitFor + " to complete..."); |
| |
| try { |
| Thread.sleep(100); |
| } catch (InterruptedException ex) { |
| Activator.log.error(ex); |
| return; |
| } |
| } |
| } |
| } |
| } |