001 /* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2013 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 package edu.wisc.ssec.mcidasv.util; 029 030 import java.util.concurrent.Callable; 031 import java.util.concurrent.CancellationException; 032 import java.util.concurrent.ExecutionException; 033 import java.util.concurrent.Future; 034 import java.util.concurrent.FutureTask; 035 import java.util.concurrent.TimeUnit; 036 import java.util.concurrent.TimeoutException; 037 038 /** 039 * Background task class supporting cancellation, completion notification, 040 * and progress notification. Courtesy of <i>Java Concurrency in Practice</i>, 041 * written by Brian Goetz and Tim Peierls. 042 */ 043 //TODO: couldn't find a license for this code? is it public domain? 044 public abstract class BackgroundTask <V> implements Runnable, Future<V> { 045 private final FutureTask<V> computation = new Computation(); 046 047 private class Computation extends FutureTask<V> { 048 public Computation() { 049 super(new Callable<V>() { 050 public V call() throws Exception { 051 return BackgroundTask.this.compute(); 052 } 053 }); 054 } 055 056 protected final void done() { 057 GuiExecutor.instance().execute(new Runnable() { 058 public void run() { 059 V value = null; 060 Throwable thrown = null; 061 boolean cancelled = false; 062 try { 063 value = get(); 064 } catch (ExecutionException e) { 065 thrown = e.getCause(); 066 } catch (CancellationException e) { 067 cancelled = true; 068 } catch (InterruptedException consumed) { 069 } finally { 070 onCompletion(value, thrown, cancelled); 071 } 072 }; 073 }); 074 } 075 } 076 077 protected void setProgress(final int current, final int max) { 078 GuiExecutor.instance().execute(new Runnable() { 079 public void run() { 080 onProgress(current, max); 081 } 082 }); 083 } 084 085 // Called in the background thread 086 protected abstract V compute() throws Exception; 087 088 // Called in the event thread 089 protected void onCompletion(V result, Throwable exception, 090 boolean cancelled) { 091 } 092 093 protected void onProgress(int current, int max) { 094 } 095 096 // Other Future methods just forwarded to computation 097 public boolean cancel(boolean mayInterruptIfRunning) { 098 return computation.cancel(mayInterruptIfRunning); 099 } 100 101 public V get() throws InterruptedException, ExecutionException { 102 return computation.get(); 103 } 104 105 public V get(long timeout, TimeUnit unit) 106 throws InterruptedException, 107 ExecutionException, 108 TimeoutException { 109 return computation.get(timeout, unit); 110 } 111 112 public boolean isCancelled() { 113 return computation.isCancelled(); 114 } 115 116 public boolean isDone() { 117 return computation.isDone(); 118 } 119 120 public void run() { 121 computation.run(); 122 } 123 }