1 // Copyright 2016 Google Inc. All Rights Reserved. 2 package com.android.contacts.util.concurrent; 3 4 import android.os.Handler; 5 6 import com.google.common.util.concurrent.FutureFallback; 7 import com.google.common.util.concurrent.Futures; 8 import com.google.common.util.concurrent.ListenableFuture; 9 10 import java.util.concurrent.CancellationException; 11 import java.util.concurrent.ScheduledExecutorService; 12 import java.util.concurrent.TimeUnit; 13 import java.util.concurrent.TimeoutException; 14 import java.util.concurrent.atomic.AtomicBoolean; 15 16 /** 17 * Has utility methods for operating on ListenableFutures 18 */ 19 public class FuturesUtil { 20 21 /** 22 * See 23 * {@link FuturesUtil#withTimeout(ListenableFuture, long, TimeUnit, ScheduledExecutorService)} 24 */ withTimeout(final ListenableFuture<V> future, long time, TimeUnit unit, Handler handler)25 public static <V> ListenableFuture<V> withTimeout(final ListenableFuture<V> future, long time, 26 TimeUnit unit, Handler handler) { 27 return withTimeout(future, time, unit, ContactsExecutors.newHandlerExecutor(handler)); 28 } 29 30 /** 31 * Returns a future that completes with the result from the input future unless the specified 32 * time elapses before it finishes in which case the result will contain a TimeoutException and 33 * the input future will be canceled. 34 * 35 * <p>Guava has Futures.withTimeout but it isn't available until v19.0 and we depend on v14.0 36 * right now. Replace usages of this method if we upgrade our dependency.</p> 37 */ withTimeout(final ListenableFuture<V> future, long time, TimeUnit unit, ScheduledExecutorService executor)38 public static <V> ListenableFuture<V> withTimeout(final ListenableFuture<V> future, long time, 39 TimeUnit unit, ScheduledExecutorService executor) { 40 final AtomicBoolean didTimeout = new AtomicBoolean(false); 41 executor.schedule(new Runnable() { 42 @Override 43 public void run() { 44 didTimeout.set(!future.isDone() && !future.isCancelled()); 45 future.cancel(true); 46 } 47 }, time, unit); 48 49 return Futures.withFallback(future, new FutureFallback<V>() { 50 @Override 51 public ListenableFuture<V> create(Throwable t) throws Exception { 52 if ((t instanceof CancellationException) && didTimeout.get()) { 53 return Futures.immediateFailedFuture(new TimeoutException("Timeout expired")); 54 } 55 return Futures.immediateFailedFuture(t); 56 } 57 }); 58 } 59 } 60