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