/* * Copyright (C) 2010-2014 JPEXS, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.jpexs.helpers; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.RunnableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * * @author JPEXS * @param */ public abstract class CancellableWorker implements RunnableFuture { private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); private static List workers = Collections.synchronizedList(new ArrayList()); private final FutureTask future; public CancellableWorker() { super(); Callable callable = new Callable() { @Override public T call() throws Exception { return doInBackground(); } }; future = new FutureTask(callable) { @Override protected void done() { workerDone(); } }; } protected abstract T doInBackground() throws Exception; @Override public final void run() { workers.add(this); future.run(); } protected void done() { } public final void execute() { THREAD_POOL.execute(this); } @Override public final boolean cancel(boolean mayInterruptIfRunning) { return future.cancel(mayInterruptIfRunning); } @Override public final boolean isCancelled() { return future.isCancelled(); } @Override public final boolean isDone() { return future.isDone(); } @Override public final T get() throws InterruptedException, ExecutionException { return future.get(); } @Override public final T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return future.get(timeout, unit); } private void workerDone() { workers.remove(this); done(); } public static T call(final Callable c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { CancellableWorker worker = new CancellableWorker() { @Override protected T doInBackground() throws Exception { return c.call(); } }; try { worker.execute(); return worker.get(timeout, timeUnit); } finally { worker.cancel(true); } } public static void cancelBackgroundThreads() { List oldWorkers = workers; workers = new ArrayList<>(); for (CancellableWorker worker : oldWorkers) { worker.cancel(true); } } }