1 // Copyright 2011 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.tools
.development
;
5 import java
.util
.concurrent
.ExecutionException
;
6 import java
.util
.concurrent
.TimeoutException
;
7 import java
.util
.concurrent
.TimeUnit
;
8 import java
.util
.concurrent
.Future
;
11 * {@code TimedFuture} is a {@link Future} that will not return
12 * successfully after the specified amount of time has elapsed.
14 * <p>All methods call through to the underlying future. However, if
15 * the specified time elapses (either before or while in one of the
16 * {@code get} methods), an ExecutionException will be thrown that
17 * wraps the exception returned by {@link #createDeadlineException()}.
18 * No attempt is made to automatically cancel the underlying Future in
22 public abstract class TimedFuture
<T
> implements Future
<T
> {
23 private final Future
<T
> future
;
24 private final Clock clock
;
25 private final long deadlineTime
;
27 public TimedFuture(Future
<T
> future
, long deadlineMillis
) {
28 this(future
, deadlineMillis
, Clock
.DEFAULT
);
31 public TimedFuture(Future
<T
> future
, long deadlineMillis
, Clock clock
) {
33 this.deadlineTime
= clock
.getCurrentTime() + deadlineMillis
;
38 public T
get() throws InterruptedException
, ExecutionException
{
39 long millisRemaining
= getMillisRemaining();
41 return future
.get(millisRemaining
, TimeUnit
.MILLISECONDS
);
42 } catch (TimeoutException ex
) {
43 throw new ExecutionException(createDeadlineException());
48 public T
get(long value
, TimeUnit units
)
49 throws InterruptedException
, ExecutionException
, TimeoutException
{
50 long millisRequested
= units
.toMillis(value
);
51 long millisRemaining
= getMillisRemaining();
52 if (millisRequested
< millisRemaining
) {
53 return future
.get(millisRequested
, TimeUnit
.MILLISECONDS
);
56 return future
.get(millisRemaining
, TimeUnit
.MILLISECONDS
);
57 } catch (TimeoutException ex
) {
58 throw new ExecutionException(createDeadlineException());
62 protected abstract RuntimeException
createDeadlineException();
64 private long getMillisRemaining() {
65 return Math
.max(0, deadlineTime
- clock
.getCurrentTime());
69 public boolean isCancelled() {
70 return future
.isCancelled();
74 public boolean isDone() {
75 return future
.isDone() || getMillisRemaining() == 0;
79 public boolean cancel(boolean force
) {
80 return future
.cancel(force
);