blob: 113af93ceb252d1c06a74a5f41f29c8bb44b5e0e [file] [log] [blame]
Marcus Hagerotta89f5232016-12-07 10:04:00 -08001// Copyright 2016 Google Inc. All Rights Reserved.
2package com.android.contacts.util.concurrent;
3
4import android.os.Handler;
5
6import com.google.common.util.concurrent.FutureFallback;
7import com.google.common.util.concurrent.Futures;
8import com.google.common.util.concurrent.ListenableFuture;
9
10import java.util.concurrent.CancellationException;
11import java.util.concurrent.ScheduledExecutorService;
12import java.util.concurrent.TimeUnit;
13import java.util.concurrent.TimeoutException;
14import java.util.concurrent.atomic.AtomicBoolean;
15
16/**
17 * Has utility methods for operating on ListenableFutures
18 */
19public class FuturesUtil {
20
21 /**
22 * See
23 * {@link FuturesUtil#withTimeout(ListenableFuture, long, TimeUnit, ScheduledExecutorService)}
24 */
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 */
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}