GNU Classpath (0.97.2) | |
Frames | No Frames |
1: /* 2: * Written by Doug Lea with assistance from members of JCP JSR-166 3: * Expert Group and released to the public domain, as explained at 4: * http://creativecommons.org/licenses/publicdomain 5: */ 6: 7: package java.util.concurrent; 8: import java.util.concurrent.locks.*; 9: 10: /** 11: * A cancellable asynchronous computation. This class provides a base 12: * implementation of {@link Future}, with methods to start and cancel 13: * a computation, query to see if the computation is complete, and 14: * retrieve the result of the computation. The result can only be 15: * retrieved when the computation has completed; the <tt>get</tt> 16: * method will block if the computation has not yet completed. Once 17: * the computation has completed, the computation cannot be restarted 18: * or cancelled. 19: * 20: * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or 21: * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt> 22: * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be 23: * submitted to an {@link Executor} for execution. 24: * 25: * <p>In addition to serving as a standalone class, this class provides 26: * <tt>protected</tt> functionality that may be useful when creating 27: * customized task classes. 28: * 29: * @since 1.5 30: * @author Doug Lea 31: * @param <V> The result type returned by this FutureTask's <tt>get</tt> method 32: */ 33: public class FutureTask<V> implements RunnableFuture<V> { 34: /** Synchronization control for FutureTask */ 35: private final Sync sync; 36: 37: /** 38: * Creates a <tt>FutureTask</tt> that will upon running, execute the 39: * given <tt>Callable</tt>. 40: * 41: * @param callable the callable task 42: * @throws NullPointerException if callable is null 43: */ 44: public FutureTask(Callable<V> callable) { 45: if (callable == null) 46: throw new NullPointerException(); 47: sync = new Sync(callable); 48: } 49: 50: /** 51: * Creates a <tt>FutureTask</tt> that will upon running, execute the 52: * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the 53: * given result on successful completion. 54: * 55: * @param runnable the runnable task 56: * @param result the result to return on successful completion. If 57: * you don't need a particular result, consider using 58: * constructions of the form: 59: * <tt>Future<?> f = new FutureTask<Object>(runnable, null)</tt> 60: * @throws NullPointerException if runnable is null 61: */ 62: public FutureTask(Runnable runnable, V result) { 63: sync = new Sync(Executors.callable(runnable, result)); 64: } 65: 66: public boolean isCancelled() { 67: return sync.innerIsCancelled(); 68: } 69: 70: public boolean isDone() { 71: return sync.innerIsDone(); 72: } 73: 74: public boolean cancel(boolean mayInterruptIfRunning) { 75: return sync.innerCancel(mayInterruptIfRunning); 76: } 77: 78: /** 79: * @throws CancellationException {@inheritDoc} 80: */ 81: public V get() throws InterruptedException, ExecutionException { 82: return sync.innerGet(); 83: } 84: 85: /** 86: * @throws CancellationException {@inheritDoc} 87: */ 88: public V get(long timeout, TimeUnit unit) 89: throws InterruptedException, ExecutionException, TimeoutException { 90: return sync.innerGet(unit.toNanos(timeout)); 91: } 92: 93: /** 94: * Protected method invoked when this task transitions to state 95: * <tt>isDone</tt> (whether normally or via cancellation). The 96: * default implementation does nothing. Subclasses may override 97: * this method to invoke completion callbacks or perform 98: * bookkeeping. Note that you can query status inside the 99: * implementation of this method to determine whether this task 100: * has been cancelled. 101: */ 102: protected void done() { } 103: 104: /** 105: * Sets the result of this Future to the given value unless 106: * this future has already been set or has been cancelled. 107: * This method is invoked internally by the <tt>run</tt> method 108: * upon successful completion of the computation. 109: * @param v the value 110: */ 111: protected void set(V v) { 112: sync.innerSet(v); 113: } 114: 115: /** 116: * Causes this future to report an <tt>ExecutionException</tt> 117: * with the given throwable as its cause, unless this Future has 118: * already been set or has been cancelled. 119: * This method is invoked internally by the <tt>run</tt> method 120: * upon failure of the computation. 121: * @param t the cause of failure 122: */ 123: protected void setException(Throwable t) { 124: sync.innerSetException(t); 125: } 126: 127: // The following (duplicated) doc comment can be removed once 128: // 129: // 6270645: Javadoc comments should be inherited from most derived 130: // superinterface or superclass 131: // is fixed. 132: /** 133: * Sets this Future to the result of its computation 134: * unless it has been cancelled. 135: */ 136: public void run() { 137: sync.innerRun(); 138: } 139: 140: /** 141: * Executes the computation without setting its result, and then 142: * resets this Future to initial state, failing to do so if the 143: * computation encounters an exception or is cancelled. This is 144: * designed for use with tasks that intrinsically execute more 145: * than once. 146: * @return true if successfully run and reset 147: */ 148: protected boolean runAndReset() { 149: return sync.innerRunAndReset(); 150: } 151: 152: /** 153: * Synchronization control for FutureTask. Note that this must be 154: * a non-static inner class in order to invoke the protected 155: * <tt>done</tt> method. For clarity, all inner class support 156: * methods are same as outer, prefixed with "inner". 157: * 158: * Uses AQS sync state to represent run status 159: */ 160: private final class Sync extends AbstractQueuedSynchronizer { 161: private static final long serialVersionUID = -7828117401763700385L; 162: 163: /** State value representing that task is running */ 164: private static final int RUNNING = 1; 165: /** State value representing that task ran */ 166: private static final int RAN = 2; 167: /** State value representing that task was cancelled */ 168: private static final int CANCELLED = 4; 169: 170: /** The underlying callable */ 171: private final Callable<V> callable; 172: /** The result to return from get() */ 173: private V result; 174: /** The exception to throw from get() */ 175: private Throwable exception; 176: 177: /** 178: * The thread running task. When nulled after set/cancel, this 179: * indicates that the results are accessible. Must be 180: * volatile, to ensure visibility upon completion. 181: */ 182: private volatile Thread runner; 183: 184: Sync(Callable<V> callable) { 185: this.callable = callable; 186: } 187: 188: private boolean ranOrCancelled(int state) { 189: return (state & (RAN | CANCELLED)) != 0; 190: } 191: 192: /** 193: * Implements AQS base acquire to succeed if ran or cancelled 194: */ 195: protected int tryAcquireShared(int ignore) { 196: return innerIsDone()? 1 : -1; 197: } 198: 199: /** 200: * Implements AQS base release to always signal after setting 201: * final done status by nulling runner thread. 202: */ 203: protected boolean tryReleaseShared(int ignore) { 204: runner = null; 205: return true; 206: } 207: 208: boolean innerIsCancelled() { 209: return getState() == CANCELLED; 210: } 211: 212: boolean innerIsDone() { 213: return ranOrCancelled(getState()) && runner == null; 214: } 215: 216: V innerGet() throws InterruptedException, ExecutionException { 217: acquireSharedInterruptibly(0); 218: if (getState() == CANCELLED) 219: throw new CancellationException(); 220: if (exception != null) 221: throw new ExecutionException(exception); 222: return result; 223: } 224: 225: V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException { 226: if (!tryAcquireSharedNanos(0, nanosTimeout)) 227: throw new TimeoutException(); 228: if (getState() == CANCELLED) 229: throw new CancellationException(); 230: if (exception != null) 231: throw new ExecutionException(exception); 232: return result; 233: } 234: 235: void innerSet(V v) { 236: for (;;) { 237: int s = getState(); 238: if (s == RAN) 239: return; 240: if (s == CANCELLED) { 241: // aggressively release to set runner to null, 242: // in case we are racing with a cancel request 243: // that will try to interrupt runner 244: releaseShared(0); 245: return; 246: } 247: if (compareAndSetState(s, RAN)) { 248: result = v; 249: releaseShared(0); 250: done(); 251: return; 252: } 253: } 254: } 255: 256: void innerSetException(Throwable t) { 257: for (;;) { 258: int s = getState(); 259: if (s == RAN) 260: return; 261: if (s == CANCELLED) { 262: // aggressively release to set runner to null, 263: // in case we are racing with a cancel request 264: // that will try to interrupt runner 265: releaseShared(0); 266: return; 267: } 268: if (compareAndSetState(s, RAN)) { 269: exception = t; 270: result = null; 271: releaseShared(0); 272: done(); 273: return; 274: } 275: } 276: } 277: 278: boolean innerCancel(boolean mayInterruptIfRunning) { 279: for (;;) { 280: int s = getState(); 281: if (ranOrCancelled(s)) 282: return false; 283: if (compareAndSetState(s, CANCELLED)) 284: break; 285: } 286: if (mayInterruptIfRunning) { 287: Thread r = runner; 288: if (r != null) 289: r.interrupt(); 290: } 291: releaseShared(0); 292: done(); 293: return true; 294: } 295: 296: void innerRun() { 297: if (!compareAndSetState(0, RUNNING)) 298: return; 299: try { 300: runner = Thread.currentThread(); 301: if (getState() == RUNNING) // recheck after setting thread 302: innerSet(callable.call()); 303: else 304: releaseShared(0); // cancel 305: } catch (Throwable ex) { 306: innerSetException(ex); 307: } 308: } 309: 310: boolean innerRunAndReset() { 311: if (!compareAndSetState(0, RUNNING)) 312: return false; 313: try { 314: runner = Thread.currentThread(); 315: if (getState() == RUNNING) 316: callable.call(); // don't set result 317: runner = null; 318: return compareAndSetState(RUNNING, 0); 319: } catch (Throwable ex) { 320: innerSetException(ex); 321: return false; 322: } 323: } 324: } 325: }
GNU Classpath (0.97.2) |