Closed GoogleCodeExporter closed 9 years ago
Here is a sample implementation using joda-time (easily replaced):
/**
* A future with a predetermined execution path.
*
* @param <V> the return type of the Future
*/
public class PredeterminedFuture<V> implements Future<V>
{
private boolean cancelled;
private boolean done;
private final V value;
private final Throwable throwable;
private final DateTime publishTime;
/**
* Creates a new PredeterminedFuture.
*
* If <code>throwable</code> is non-null, the Future will throw the exception; otherwise,
* it return the value.
*
* @param value the value to return
* @param throwable the Throwable to throw
* @param timeout the amount of time to wait before publishing the result
* @param unit the unit of timeout
*/
public PredeterminedFuture(V value, Throwable throwable, long timeout, TimeUnit unit)
{
this.value = value;
this.throwable = throwable;
if (timeout == Long.MAX_VALUE)
{
// never publish the result
this.publishTime = null;
}
else
this.publishTime = new DateTime(unit.toMillis(timeout));
}
@Override
public synchronized boolean cancel(boolean mayInterruptIfRunning)
{
if (publishTime == null || publishTime.isAfterNow())
{
cancelled = true;
done = true;
notifyAll();
}
return cancelled;
}
@Override
public synchronized boolean isCancelled()
{
return cancelled;
}
@Override
public synchronized boolean isDone()
{
return done;
}
/**
* Waits until the Future is done or times out.
*
* @param wakeupTime indicates when to return even if <code>done</code> is false, null of
* the method should wait for <code>done</code>
* @throws InterruptedException if the thread is interrupted
*/
private synchronized void waitUntil(DateTime wakeupTime) throws InterruptedException
{
while (!done)
{
long timeLeft;
if (wakeupTime == null)
timeLeft = Long.MAX_VALUE;
else
{
DateTime now = new DateTime();
timeLeft = new Duration(now, wakeupTime).getMillis();
}
if (timeLeft <= 0)
{
done = true;
break;
}
TimeUnit.MILLISECONDS.timedWait(this, timeLeft);
}
}
@Override
public synchronized V get() throws InterruptedException, ExecutionException
{
waitUntil(publishTime);
if (cancelled)
throw new CancellationException();
if (throwable != null)
throw new ExecutionException(throwable);
return value;
}
@Override
public synchronized V get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException
{
DateTime startTime = new DateTime();
DateTime earliestEvent = startTime.plus(unit.toMillis(timeout));
if (publishTime != null && publishTime.isBefore(earliestEvent))
earliestEvent = publishTime;
waitUntil(earliestEvent);
if (cancelled)
throw new CancellationException();
if (throwable != null)
throw new ExecutionException(throwable);
return value;
}
}
Original comment by cowwoc...@gmail.com
on 23 Nov 2010 at 10:38
Updated source-code. Future.get(long, TimeUnit) was never throwing
TimeoutException.
Original comment by cowwoc...@gmail.com
on 24 Nov 2010 at 2:46
Attachments:
I'm a little confused; is your need for a Future that always times out, or one
that populates after a set period of time? This report seems to mix the two.
These things seem like they would have pretty limited use outside of testing
(and possibly dangerous in testing, when those timeouts invariably lead to
flaky tests).
Original comment by kevinb@google.com
on 12 Jan 2011 at 10:44
Original comment by kevinb@google.com
on 12 Jan 2011 at 11:12
In retrospect, my specific case (implementing the Null Object Pattern for a
disconnected device) needed a Future that always times out (not one that
populates with a value/exception after a certain amount of time). This object
was used at runtime, not in test code.
Original comment by cowwoc...@gmail.com
on 12 Jan 2011 at 11:17
Would be very good to hear if anyone else needs this.
Original comment by kevinb@google.com
on 26 Jan 2011 at 2:24
A future that blocks forever on get() (until interrupted) sounds like fun, if
only for testing.
But it can easily be done with SettableFuture?
Original comment by earwin@gmail.com
on 5 Jun 2011 at 1:44
Original comment by kevinb@google.com
on 13 Jul 2011 at 6:18
That's true, earwin.
Original comment by kevinb@google.com
on 1 Aug 2011 at 9:24
This issue has been migrated to GitHub.
It can be found at https://github.com/google/guava/issues/<id>
Original comment by cgdecker@google.com
on 1 Nov 2014 at 4:15
Original comment by cgdecker@google.com
on 3 Nov 2014 at 9:09
Original issue reported on code.google.com by
cowwoc...@gmail.com
on 23 Nov 2010 at 9:32