• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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